xref: /trunk/main/extensions/source/scanner/scanwin.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1*cdf0e10cSrcweir /*************************************************************************
2*cdf0e10cSrcweir  *
3*cdf0e10cSrcweir  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4*cdf0e10cSrcweir  *
5*cdf0e10cSrcweir  * Copyright 2000, 2010 Oracle and/or its affiliates.
6*cdf0e10cSrcweir  *
7*cdf0e10cSrcweir  * OpenOffice.org - a multi-platform office productivity suite
8*cdf0e10cSrcweir  *
9*cdf0e10cSrcweir  * This file is part of OpenOffice.org.
10*cdf0e10cSrcweir  *
11*cdf0e10cSrcweir  * OpenOffice.org is free software: you can redistribute it and/or modify
12*cdf0e10cSrcweir  * it under the terms of the GNU Lesser General Public License version 3
13*cdf0e10cSrcweir  * only, as published by the Free Software Foundation.
14*cdf0e10cSrcweir  *
15*cdf0e10cSrcweir  * OpenOffice.org is distributed in the hope that it will be useful,
16*cdf0e10cSrcweir  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17*cdf0e10cSrcweir  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18*cdf0e10cSrcweir  * GNU Lesser General Public License version 3 for more details
19*cdf0e10cSrcweir  * (a copy is included in the LICENSE file that accompanied this code).
20*cdf0e10cSrcweir  *
21*cdf0e10cSrcweir  * You should have received a copy of the GNU Lesser General Public License
22*cdf0e10cSrcweir  * version 3 along with OpenOffice.org.  If not, see
23*cdf0e10cSrcweir  * <http://www.openoffice.org/license.html>
24*cdf0e10cSrcweir  * for a copy of the LGPLv3 License.
25*cdf0e10cSrcweir  *
26*cdf0e10cSrcweir  ************************************************************************/
27*cdf0e10cSrcweir 
28*cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
29*cdf0e10cSrcweir #include "precompiled_extensions.hxx"
30*cdf0e10cSrcweir #include <com/sun/star/uno/Any.hxx>
31*cdf0e10cSrcweir #include <com/sun/star/uno/Reference.hxx>
32*cdf0e10cSrcweir #include <com/sun/star/util/XCloseable.hpp>
33*cdf0e10cSrcweir #include <com/sun/star/util/XCloseBroadcaster.hpp>
34*cdf0e10cSrcweir #include <com/sun/star/util/XCloseListener.hpp>
35*cdf0e10cSrcweir #include <com/sun/star/frame/XFrame.hpp>
36*cdf0e10cSrcweir #include <com/sun/star/frame/XDesktop.hpp>
37*cdf0e10cSrcweir #include <com/sun/star/beans/XPropertySet.hpp>
38*cdf0e10cSrcweir #include <cppuhelper/implbase1.hxx>
39*cdf0e10cSrcweir #include <comphelper/processfactory.hxx>
40*cdf0e10cSrcweir 
41*cdf0e10cSrcweir #include <math.h>
42*cdf0e10cSrcweir #include <tools/svwin.h>
43*cdf0e10cSrcweir #include <tools/stream.hxx>
44*cdf0e10cSrcweir #include <vos/mutex.hxx>
45*cdf0e10cSrcweir #include <vos/module.hxx>
46*cdf0e10cSrcweir #include <vcl/svapp.hxx>
47*cdf0e10cSrcweir #include <vcl/wrkwin.hxx>
48*cdf0e10cSrcweir #include <vcl/sysdata.hxx>
49*cdf0e10cSrcweir #include <vcl/salbtype.hxx>
50*cdf0e10cSrcweir #include "scanner.hxx"
51*cdf0e10cSrcweir 
52*cdf0e10cSrcweir #pragma warning (push,1)
53*cdf0e10cSrcweir #pragma warning (disable:4668)
54*cdf0e10cSrcweir #include "twain/twain.h"
55*cdf0e10cSrcweir #pragma warning (pop)
56*cdf0e10cSrcweir 
57*cdf0e10cSrcweir using namespace ::com::sun::star;
58*cdf0e10cSrcweir 
59*cdf0e10cSrcweir // -----------
60*cdf0e10cSrcweir // - Defines -
61*cdf0e10cSrcweir // -----------
62*cdf0e10cSrcweir 
63*cdf0e10cSrcweir #define TWAIN_SELECT            0x00000001UL
64*cdf0e10cSrcweir #define TWAIN_ACQUIRE           0x00000002UL
65*cdf0e10cSrcweir #define TWAIN_TERMINATE         0xFFFFFFFFUL
66*cdf0e10cSrcweir 
67*cdf0e10cSrcweir #define TWAIN_EVENT_NONE        0x00000000UL
68*cdf0e10cSrcweir #define TWAIN_EVENT_QUIT        0x00000001UL
69*cdf0e10cSrcweir #define TWAIN_EVENT_SCANNING    0x00000002UL
70*cdf0e10cSrcweir #define TWAIN_EVENT_XFER        0x00000004UL
71*cdf0e10cSrcweir 
72*cdf0e10cSrcweir #define PFUNC                   (*pDSM)
73*cdf0e10cSrcweir #define PTWAINMSG               MSG*
74*cdf0e10cSrcweir #define FIXTODOUBLE( nFix )     ((double)nFix.Whole+(double)nFix.Frac/65536.)
75*cdf0e10cSrcweir #define FIXTOLONG( nFix )       ((long)floor(FIXTODOUBLE(nFix)+0.5))
76*cdf0e10cSrcweir 
77*cdf0e10cSrcweir #if defined WNT
78*cdf0e10cSrcweir #define TWAIN_LIBNAME           "TWAIN_32.DLL"
79*cdf0e10cSrcweir #define TWAIN_FUNCNAME          "DSM_Entry"
80*cdf0e10cSrcweir #endif
81*cdf0e10cSrcweir 
82*cdf0e10cSrcweir // --------------
83*cdf0e10cSrcweir // - TwainState -
84*cdf0e10cSrcweir // --------------
85*cdf0e10cSrcweir 
86*cdf0e10cSrcweir enum TwainState
87*cdf0e10cSrcweir {
88*cdf0e10cSrcweir     TWAIN_STATE_NONE = 0,
89*cdf0e10cSrcweir     TWAIN_STATE_SCANNING = 1,
90*cdf0e10cSrcweir     TWAIN_STATE_DONE = 2,
91*cdf0e10cSrcweir     TWAIN_STATE_CANCELED = 3
92*cdf0e10cSrcweir };
93*cdf0e10cSrcweir 
94*cdf0e10cSrcweir // ------------
95*cdf0e10cSrcweir // - ImpTwain -
96*cdf0e10cSrcweir // ------------
97*cdf0e10cSrcweir 
98*cdf0e10cSrcweir class ImpTwain : public ::cppu::WeakImplHelper1< util::XCloseListener >
99*cdf0e10cSrcweir {
100*cdf0e10cSrcweir     friend LRESULT CALLBACK TwainMsgProc( int nCode, WPARAM wParam, LPARAM lParam );
101*cdf0e10cSrcweir 
102*cdf0e10cSrcweir     uno::Reference< uno::XInterface >           mxSelfRef;
103*cdf0e10cSrcweir     uno::Reference< scanner::XScannerManager >  mxMgr;
104*cdf0e10cSrcweir     ScannerManager&                             mrMgr;
105*cdf0e10cSrcweir     TW_IDENTITY                                 aAppIdent;
106*cdf0e10cSrcweir     TW_IDENTITY                                 aSrcIdent;
107*cdf0e10cSrcweir     Link                                        aNotifyLink;
108*cdf0e10cSrcweir     DSMENTRYPROC                                pDSM;
109*cdf0e10cSrcweir     vos:: OModule *                 pMod;
110*cdf0e10cSrcweir     ULONG                                       nCurState;
111*cdf0e10cSrcweir     HWND                                        hTwainWnd;
112*cdf0e10cSrcweir     HHOOK                                       hTwainHook;
113*cdf0e10cSrcweir     bool                                        mbCloseFrameOnExit;
114*cdf0e10cSrcweir 
115*cdf0e10cSrcweir     bool                                        ImplHandleMsg( void* pMsg );
116*cdf0e10cSrcweir     void                                        ImplCreate();
117*cdf0e10cSrcweir     void                                        ImplOpenSourceManager();
118*cdf0e10cSrcweir     void                                        ImplOpenSource();
119*cdf0e10cSrcweir     bool                                        ImplEnableSource();
120*cdf0e10cSrcweir     void                                        ImplXfer();
121*cdf0e10cSrcweir     void                                        ImplFallback( ULONG nEvent );
122*cdf0e10cSrcweir     void                                        ImplSendCloseEvent();
123*cdf0e10cSrcweir     void                                        ImplDeregisterCloseListener();
124*cdf0e10cSrcweir     void                                        ImplRegisterCloseListener();
125*cdf0e10cSrcweir     uno::Reference< frame::XFrame >             ImplGetActiveFrame();
126*cdf0e10cSrcweir     uno::Reference< util::XCloseBroadcaster >   ImplGetActiveFrameCloseBroadcaster();
127*cdf0e10cSrcweir 
128*cdf0e10cSrcweir                                                 DECL_LINK( ImplFallbackHdl, void* );
129*cdf0e10cSrcweir                                                 DECL_LINK( ImplDestroyHdl, void* );
130*cdf0e10cSrcweir 
131*cdf0e10cSrcweir     // from util::XCloseListener
132*cdf0e10cSrcweir     virtual void SAL_CALL queryClosing( const lang::EventObject& Source, sal_Bool GetsOwnership ) throw (util::CloseVetoException, uno::RuntimeException);
133*cdf0e10cSrcweir     virtual void SAL_CALL notifyClosing( const lang::EventObject& Source ) throw (uno::RuntimeException);
134*cdf0e10cSrcweir 
135*cdf0e10cSrcweir     // from lang::XEventListener
136*cdf0e10cSrcweir     virtual void SAL_CALL disposing( const lang::EventObject& Source ) throw (uno::RuntimeException);
137*cdf0e10cSrcweir 
138*cdf0e10cSrcweir public:
139*cdf0e10cSrcweir 
140*cdf0e10cSrcweir                                                 ImpTwain( ScannerManager& rMgr, const Link& rNotifyLink );
141*cdf0e10cSrcweir                                                 ~ImpTwain();
142*cdf0e10cSrcweir 
143*cdf0e10cSrcweir     void                                        Destroy();
144*cdf0e10cSrcweir 
145*cdf0e10cSrcweir     bool                                        SelectSource();
146*cdf0e10cSrcweir     bool                                        InitXfer();
147*cdf0e10cSrcweir };
148*cdf0e10cSrcweir 
149*cdf0e10cSrcweir // ---------
150*cdf0e10cSrcweir // - Procs -
151*cdf0e10cSrcweir // ---------
152*cdf0e10cSrcweir 
153*cdf0e10cSrcweir static ImpTwain* pImpTwainInstance = NULL;
154*cdf0e10cSrcweir 
155*cdf0e10cSrcweir // -------------------------------------------------------------------------
156*cdf0e10cSrcweir 
157*cdf0e10cSrcweir LRESULT CALLBACK TwainWndProc( HWND hWnd,UINT nMsg, WPARAM nPar1, LPARAM nPar2 )
158*cdf0e10cSrcweir {
159*cdf0e10cSrcweir     return DefWindowProc( hWnd, nMsg, nPar1, nPar2 );
160*cdf0e10cSrcweir }
161*cdf0e10cSrcweir 
162*cdf0e10cSrcweir // -------------------------------------------------------------------------
163*cdf0e10cSrcweir 
164*cdf0e10cSrcweir LRESULT CALLBACK TwainMsgProc( int nCode, WPARAM wParam, LPARAM lParam )
165*cdf0e10cSrcweir {
166*cdf0e10cSrcweir     MSG* pMsg = (MSG*) lParam;
167*cdf0e10cSrcweir 
168*cdf0e10cSrcweir     if( ( nCode < 0 ) || ( pImpTwainInstance->hTwainWnd != pMsg->hwnd ) || !pImpTwainInstance->ImplHandleMsg( (void*) lParam ) )
169*cdf0e10cSrcweir     {
170*cdf0e10cSrcweir         return CallNextHookEx( pImpTwainInstance->hTwainHook, nCode, wParam, lParam );
171*cdf0e10cSrcweir     }
172*cdf0e10cSrcweir     else
173*cdf0e10cSrcweir     {
174*cdf0e10cSrcweir         pMsg->message = WM_USER;
175*cdf0e10cSrcweir         pMsg->lParam = 0;
176*cdf0e10cSrcweir 
177*cdf0e10cSrcweir         return 0;
178*cdf0e10cSrcweir     }
179*cdf0e10cSrcweir }
180*cdf0e10cSrcweir 
181*cdf0e10cSrcweir // -----------------------------------------------------------------------------
182*cdf0e10cSrcweir 
183*cdf0e10cSrcweir // #107835# hold reference to ScannerManager, to prevent premature death
184*cdf0e10cSrcweir ImpTwain::ImpTwain( ScannerManager& rMgr, const Link& rNotifyLink ) :
185*cdf0e10cSrcweir             mrMgr( rMgr ),
186*cdf0e10cSrcweir             mxMgr( uno::Reference< scanner::XScannerManager >( static_cast< OWeakObject* >( &rMgr ), uno::UNO_QUERY) ),
187*cdf0e10cSrcweir             aNotifyLink( rNotifyLink ),
188*cdf0e10cSrcweir             pDSM( NULL ),
189*cdf0e10cSrcweir             pMod( NULL ),
190*cdf0e10cSrcweir             hTwainWnd( 0 ),
191*cdf0e10cSrcweir             hTwainHook( 0 ),
192*cdf0e10cSrcweir             nCurState( 1 ),
193*cdf0e10cSrcweir             mbCloseFrameOnExit( false )
194*cdf0e10cSrcweir {
195*cdf0e10cSrcweir     // setup TWAIN window
196*cdf0e10cSrcweir     pImpTwainInstance = this;
197*cdf0e10cSrcweir 
198*cdf0e10cSrcweir     aAppIdent.Id = 0;
199*cdf0e10cSrcweir     aAppIdent.Version.MajorNum = 1;
200*cdf0e10cSrcweir     aAppIdent.Version.MinorNum = 0;
201*cdf0e10cSrcweir     aAppIdent.Version.Language = TWLG_USA;
202*cdf0e10cSrcweir     aAppIdent.Version.Country = TWCY_USA;
203*cdf0e10cSrcweir     aAppIdent.ProtocolMajor = TWON_PROTOCOLMAJOR;
204*cdf0e10cSrcweir     aAppIdent.ProtocolMinor = TWON_PROTOCOLMINOR;
205*cdf0e10cSrcweir     aAppIdent.SupportedGroups = DG_IMAGE | DG_CONTROL;
206*cdf0e10cSrcweir     strncpy( aAppIdent.Version.Info, "8.0", 32 );
207*cdf0e10cSrcweir     aAppIdent.Version.Info[32] = aAppIdent.Version.Info[33] = 0;
208*cdf0e10cSrcweir     strncpy( aAppIdent.Manufacturer, "Sun Microsystems", 32 );
209*cdf0e10cSrcweir     aAppIdent.Manufacturer[32] = aAppIdent.Manufacturer[33] = 0;
210*cdf0e10cSrcweir     strncpy( aAppIdent.ProductFamily,"Office", 32 );
211*cdf0e10cSrcweir     aAppIdent.ProductFamily[32] = aAppIdent.ProductFamily[33] = 0;
212*cdf0e10cSrcweir     strncpy( aAppIdent.ProductName, "Office", 32 );
213*cdf0e10cSrcweir     aAppIdent.ProductName[32] = aAppIdent.ProductName[33] = 0;
214*cdf0e10cSrcweir 
215*cdf0e10cSrcweir     WNDCLASS aWc = { 0, &TwainWndProc, 0, sizeof( WNDCLASS ), GetModuleHandle( NULL ), NULL, NULL, NULL, NULL, "TwainClass" };
216*cdf0e10cSrcweir     RegisterClass( &aWc );
217*cdf0e10cSrcweir 
218*cdf0e10cSrcweir     hTwainWnd = CreateWindowEx( WS_EX_TOPMOST, aWc.lpszClassName, "TWAIN", 0, 0, 0, 0, 0, HWND_DESKTOP, NULL, aWc.hInstance, 0 );
219*cdf0e10cSrcweir     hTwainHook = SetWindowsHookEx( WH_GETMESSAGE, &TwainMsgProc, NULL, GetCurrentThreadId() );
220*cdf0e10cSrcweir 
221*cdf0e10cSrcweir     // #107835# block destruction until ImplDestroyHdl is called
222*cdf0e10cSrcweir     mxSelfRef = static_cast< ::cppu::OWeakObject* >( this );
223*cdf0e10cSrcweir }
224*cdf0e10cSrcweir 
225*cdf0e10cSrcweir // -----------------------------------------------------------------------------
226*cdf0e10cSrcweir 
227*cdf0e10cSrcweir ImpTwain::~ImpTwain()
228*cdf0e10cSrcweir {
229*cdf0e10cSrcweir     // are we responsible for application shutdown?
230*cdf0e10cSrcweir     if( mbCloseFrameOnExit )
231*cdf0e10cSrcweir         ImplSendCloseEvent();
232*cdf0e10cSrcweir }
233*cdf0e10cSrcweir 
234*cdf0e10cSrcweir // -----------------------------------------------------------------------------
235*cdf0e10cSrcweir 
236*cdf0e10cSrcweir void ImpTwain::Destroy()
237*cdf0e10cSrcweir {
238*cdf0e10cSrcweir     ImplFallback( TWAIN_EVENT_NONE );
239*cdf0e10cSrcweir     Application::PostUserEvent( LINK( this, ImpTwain, ImplDestroyHdl ), NULL );
240*cdf0e10cSrcweir }
241*cdf0e10cSrcweir 
242*cdf0e10cSrcweir // -----------------------------------------------------------------------------
243*cdf0e10cSrcweir 
244*cdf0e10cSrcweir bool ImpTwain::SelectSource()
245*cdf0e10cSrcweir {
246*cdf0e10cSrcweir     TW_UINT16 nRet = TWRC_FAILURE;
247*cdf0e10cSrcweir 
248*cdf0e10cSrcweir     ImplOpenSourceManager();
249*cdf0e10cSrcweir 
250*cdf0e10cSrcweir     if( 3 == nCurState )
251*cdf0e10cSrcweir     {
252*cdf0e10cSrcweir         TW_IDENTITY aIdent;
253*cdf0e10cSrcweir 
254*cdf0e10cSrcweir         aIdent.Id = 0, aIdent.ProductName[ 0 ] = '\0';
255*cdf0e10cSrcweir         aNotifyLink.Call( (void*) TWAIN_EVENT_SCANNING );
256*cdf0e10cSrcweir         nRet = PFUNC( &aAppIdent, NULL, DG_CONTROL, DAT_IDENTITY, MSG_USERSELECT, &aIdent );
257*cdf0e10cSrcweir     }
258*cdf0e10cSrcweir 
259*cdf0e10cSrcweir     ImplFallback( TWAIN_EVENT_QUIT );
260*cdf0e10cSrcweir 
261*cdf0e10cSrcweir     return( TWRC_SUCCESS == nRet );
262*cdf0e10cSrcweir }
263*cdf0e10cSrcweir 
264*cdf0e10cSrcweir // -----------------------------------------------------------------------------
265*cdf0e10cSrcweir 
266*cdf0e10cSrcweir bool ImpTwain::InitXfer()
267*cdf0e10cSrcweir {
268*cdf0e10cSrcweir     bool bRet = false;
269*cdf0e10cSrcweir 
270*cdf0e10cSrcweir     ImplOpenSourceManager();
271*cdf0e10cSrcweir 
272*cdf0e10cSrcweir     if( 3 == nCurState )
273*cdf0e10cSrcweir     {
274*cdf0e10cSrcweir         ImplOpenSource();
275*cdf0e10cSrcweir 
276*cdf0e10cSrcweir         if( 4 == nCurState )
277*cdf0e10cSrcweir             bRet = ImplEnableSource();
278*cdf0e10cSrcweir     }
279*cdf0e10cSrcweir 
280*cdf0e10cSrcweir     if( !bRet )
281*cdf0e10cSrcweir         ImplFallback( TWAIN_EVENT_QUIT );
282*cdf0e10cSrcweir 
283*cdf0e10cSrcweir     return bRet;
284*cdf0e10cSrcweir }
285*cdf0e10cSrcweir 
286*cdf0e10cSrcweir // -----------------------------------------------------------------------------
287*cdf0e10cSrcweir 
288*cdf0e10cSrcweir void ImpTwain::ImplOpenSourceManager()
289*cdf0e10cSrcweir {
290*cdf0e10cSrcweir     if( 1 == nCurState )
291*cdf0e10cSrcweir     {
292*cdf0e10cSrcweir         pMod = new ::vos::OModule( ::rtl::OUString() );
293*cdf0e10cSrcweir 
294*cdf0e10cSrcweir         if( pMod->load( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( TWAIN_LIBNAME ) ) ) )
295*cdf0e10cSrcweir         {
296*cdf0e10cSrcweir             nCurState = 2;
297*cdf0e10cSrcweir 
298*cdf0e10cSrcweir             if( ( ( pDSM = (DSMENTRYPROC) pMod->getSymbol( String( RTL_CONSTASCII_USTRINGPARAM( TWAIN_FUNCNAME ) ) ) ) != NULL ) &&
299*cdf0e10cSrcweir                 ( PFUNC( &aAppIdent, NULL, DG_CONTROL, DAT_PARENT, MSG_OPENDSM, &hTwainWnd ) == TWRC_SUCCESS ) )
300*cdf0e10cSrcweir             {
301*cdf0e10cSrcweir                 nCurState = 3;
302*cdf0e10cSrcweir             }
303*cdf0e10cSrcweir         }
304*cdf0e10cSrcweir         else
305*cdf0e10cSrcweir         {
306*cdf0e10cSrcweir             delete pMod;
307*cdf0e10cSrcweir             pMod = NULL;
308*cdf0e10cSrcweir         }
309*cdf0e10cSrcweir     }
310*cdf0e10cSrcweir }
311*cdf0e10cSrcweir 
312*cdf0e10cSrcweir // -----------------------------------------------------------------------------
313*cdf0e10cSrcweir 
314*cdf0e10cSrcweir void ImpTwain::ImplOpenSource()
315*cdf0e10cSrcweir {
316*cdf0e10cSrcweir     if( 3 == nCurState )
317*cdf0e10cSrcweir     {
318*cdf0e10cSrcweir         if( ( PFUNC( &aAppIdent, NULL, DG_CONTROL, DAT_IDENTITY, MSG_GETDEFAULT, &aSrcIdent ) == TWRC_SUCCESS ) &&
319*cdf0e10cSrcweir             ( PFUNC( &aAppIdent, NULL, DG_CONTROL, DAT_IDENTITY, MSG_OPENDS, &aSrcIdent ) == TWRC_SUCCESS ) )
320*cdf0e10cSrcweir         {
321*cdf0e10cSrcweir             TW_CAPABILITY   aCap = { CAP_XFERCOUNT, TWON_ONEVALUE, GlobalAlloc( GHND, sizeof( TW_ONEVALUE ) ) };
322*cdf0e10cSrcweir             TW_ONEVALUE*    pVal = (TW_ONEVALUE*) GlobalLock( aCap.hContainer );
323*cdf0e10cSrcweir 
324*cdf0e10cSrcweir             pVal->ItemType = TWTY_INT16, pVal->Item = 1;
325*cdf0e10cSrcweir             GlobalUnlock( aCap.hContainer );
326*cdf0e10cSrcweir             PFUNC( &aAppIdent, &aSrcIdent, DG_CONTROL, DAT_CAPABILITY, MSG_SET, &aCap );
327*cdf0e10cSrcweir             GlobalFree( aCap.hContainer );
328*cdf0e10cSrcweir             nCurState = 4;
329*cdf0e10cSrcweir         }
330*cdf0e10cSrcweir     }
331*cdf0e10cSrcweir }
332*cdf0e10cSrcweir 
333*cdf0e10cSrcweir // -----------------------------------------------------------------------------
334*cdf0e10cSrcweir 
335*cdf0e10cSrcweir bool ImpTwain::ImplEnableSource()
336*cdf0e10cSrcweir {
337*cdf0e10cSrcweir     bool bRet = false;
338*cdf0e10cSrcweir 
339*cdf0e10cSrcweir     if( 4 == nCurState )
340*cdf0e10cSrcweir     {
341*cdf0e10cSrcweir         TW_USERINTERFACE aUI = { true, true, hTwainWnd };
342*cdf0e10cSrcweir 
343*cdf0e10cSrcweir         aNotifyLink.Call( (void*) TWAIN_EVENT_SCANNING );
344*cdf0e10cSrcweir         nCurState = 5;
345*cdf0e10cSrcweir 
346*cdf0e10cSrcweir         // #107835# register as vetoable close listener, to prevent application to die under us
347*cdf0e10cSrcweir         ImplRegisterCloseListener();
348*cdf0e10cSrcweir 
349*cdf0e10cSrcweir         if( PFUNC( &aAppIdent, &aSrcIdent, DG_CONTROL, DAT_USERINTERFACE, MSG_ENABLEDS, &aUI ) == TWRC_SUCCESS )
350*cdf0e10cSrcweir         {
351*cdf0e10cSrcweir             bRet = true;
352*cdf0e10cSrcweir         }
353*cdf0e10cSrcweir         else
354*cdf0e10cSrcweir         {
355*cdf0e10cSrcweir             nCurState = 4;
356*cdf0e10cSrcweir 
357*cdf0e10cSrcweir             // #107835# deregister as vetoable close listener, dialog failed
358*cdf0e10cSrcweir             ImplDeregisterCloseListener();
359*cdf0e10cSrcweir         }
360*cdf0e10cSrcweir     }
361*cdf0e10cSrcweir 
362*cdf0e10cSrcweir     return bRet;
363*cdf0e10cSrcweir }
364*cdf0e10cSrcweir 
365*cdf0e10cSrcweir // -----------------------------------------------------------------------------
366*cdf0e10cSrcweir 
367*cdf0e10cSrcweir bool ImpTwain::ImplHandleMsg( void* pMsg )
368*cdf0e10cSrcweir {
369*cdf0e10cSrcweir     TW_UINT16   nRet;
370*cdf0e10cSrcweir     PTWAINMSG   pMess = (PTWAINMSG) pMsg;
371*cdf0e10cSrcweir     TW_EVENT    aEvt = { pMess, MSG_NULL };
372*cdf0e10cSrcweir 
373*cdf0e10cSrcweir     nRet = PFUNC( &aAppIdent, &aSrcIdent, DG_CONTROL, DAT_EVENT, MSG_PROCESSEVENT, &aEvt );
374*cdf0e10cSrcweir 
375*cdf0e10cSrcweir     if( aEvt.TWMessage != MSG_NULL )
376*cdf0e10cSrcweir     {
377*cdf0e10cSrcweir         switch( aEvt.TWMessage )
378*cdf0e10cSrcweir         {
379*cdf0e10cSrcweir             case MSG_XFERREADY:
380*cdf0e10cSrcweir             {
381*cdf0e10cSrcweir                 ULONG nEvent = TWAIN_EVENT_QUIT;
382*cdf0e10cSrcweir 
383*cdf0e10cSrcweir                 if( 5 == nCurState )
384*cdf0e10cSrcweir                 {
385*cdf0e10cSrcweir                     nCurState = 6;
386*cdf0e10cSrcweir                     ImplXfer();
387*cdf0e10cSrcweir 
388*cdf0e10cSrcweir                     if( mrMgr.GetData() )
389*cdf0e10cSrcweir                         nEvent = TWAIN_EVENT_XFER;
390*cdf0e10cSrcweir                 }
391*cdf0e10cSrcweir 
392*cdf0e10cSrcweir                 ImplFallback( nEvent );
393*cdf0e10cSrcweir             }
394*cdf0e10cSrcweir             break;
395*cdf0e10cSrcweir 
396*cdf0e10cSrcweir             case MSG_CLOSEDSREQ:
397*cdf0e10cSrcweir                 ImplFallback( TWAIN_EVENT_QUIT );
398*cdf0e10cSrcweir             break;
399*cdf0e10cSrcweir 
400*cdf0e10cSrcweir             default:
401*cdf0e10cSrcweir             break;
402*cdf0e10cSrcweir         }
403*cdf0e10cSrcweir     }
404*cdf0e10cSrcweir     else
405*cdf0e10cSrcweir         nRet = TWRC_NOTDSEVENT;
406*cdf0e10cSrcweir 
407*cdf0e10cSrcweir     return( TWRC_DSEVENT == nRet );
408*cdf0e10cSrcweir }
409*cdf0e10cSrcweir 
410*cdf0e10cSrcweir // -----------------------------------------------------------------------------
411*cdf0e10cSrcweir 
412*cdf0e10cSrcweir void ImpTwain::ImplXfer()
413*cdf0e10cSrcweir {
414*cdf0e10cSrcweir     if( nCurState == 6 )
415*cdf0e10cSrcweir     {
416*cdf0e10cSrcweir         TW_IMAGEINFO    aInfo;
417*cdf0e10cSrcweir         TW_UINT32       hDIB = 0;
418*cdf0e10cSrcweir         long            nWidth, nHeight, nXRes, nYRes;
419*cdf0e10cSrcweir 
420*cdf0e10cSrcweir         if( PFUNC( &aAppIdent, &aSrcIdent, DG_IMAGE, DAT_IMAGEINFO, MSG_GET, &aInfo ) == TWRC_SUCCESS )
421*cdf0e10cSrcweir         {
422*cdf0e10cSrcweir             nWidth = aInfo.ImageWidth;
423*cdf0e10cSrcweir             nHeight = aInfo.ImageLength;
424*cdf0e10cSrcweir             nXRes = FIXTOLONG( aInfo.XResolution );
425*cdf0e10cSrcweir             nYRes = FIXTOLONG( aInfo.YResolution );
426*cdf0e10cSrcweir         }
427*cdf0e10cSrcweir         else
428*cdf0e10cSrcweir             nWidth = nHeight = nXRes = nYRes = -1L;
429*cdf0e10cSrcweir 
430*cdf0e10cSrcweir         switch( PFUNC( &aAppIdent, &aSrcIdent, DG_IMAGE, DAT_IMAGENATIVEXFER, MSG_GET, &hDIB ) )
431*cdf0e10cSrcweir         {
432*cdf0e10cSrcweir             case( TWRC_CANCEL ):
433*cdf0e10cSrcweir                 nCurState = 7;
434*cdf0e10cSrcweir             break;
435*cdf0e10cSrcweir 
436*cdf0e10cSrcweir             case( TWRC_XFERDONE ):
437*cdf0e10cSrcweir             {
438*cdf0e10cSrcweir                 if( hDIB )
439*cdf0e10cSrcweir                 {
440*cdf0e10cSrcweir                     if( ( nXRes != -1 ) && ( nYRes != - 1 ) && ( nWidth != - 1 ) && ( nHeight != - 1 ) )
441*cdf0e10cSrcweir                     {
442*cdf0e10cSrcweir                         // set resolution of bitmap
443*cdf0e10cSrcweir                         BITMAPINFOHEADER*   pBIH = (BITMAPINFOHEADER*) GlobalLock( (HGLOBAL) hDIB );
444*cdf0e10cSrcweir                         static const double fFactor = 100.0 / 2.54;
445*cdf0e10cSrcweir 
446*cdf0e10cSrcweir                         pBIH->biXPelsPerMeter = FRound( fFactor * nXRes );
447*cdf0e10cSrcweir                         pBIH->biYPelsPerMeter = FRound( fFactor * nYRes );
448*cdf0e10cSrcweir 
449*cdf0e10cSrcweir                         GlobalUnlock( (HGLOBAL) hDIB );
450*cdf0e10cSrcweir                     }
451*cdf0e10cSrcweir 
452*cdf0e10cSrcweir                     mrMgr.SetData( (void*)(long) hDIB );
453*cdf0e10cSrcweir                 }
454*cdf0e10cSrcweir                 else
455*cdf0e10cSrcweir                     GlobalFree( (HGLOBAL) hDIB );
456*cdf0e10cSrcweir 
457*cdf0e10cSrcweir                 nCurState = 7;
458*cdf0e10cSrcweir             }
459*cdf0e10cSrcweir             break;
460*cdf0e10cSrcweir 
461*cdf0e10cSrcweir             default:
462*cdf0e10cSrcweir             break;
463*cdf0e10cSrcweir         }
464*cdf0e10cSrcweir     }
465*cdf0e10cSrcweir }
466*cdf0e10cSrcweir 
467*cdf0e10cSrcweir // -----------------------------------------------------------------------------
468*cdf0e10cSrcweir 
469*cdf0e10cSrcweir void ImpTwain::ImplFallback( ULONG nEvent )
470*cdf0e10cSrcweir {
471*cdf0e10cSrcweir     Application::PostUserEvent( LINK( this, ImpTwain, ImplFallbackHdl ), (void*) nEvent );
472*cdf0e10cSrcweir }
473*cdf0e10cSrcweir 
474*cdf0e10cSrcweir // -----------------------------------------------------------------------------
475*cdf0e10cSrcweir 
476*cdf0e10cSrcweir IMPL_LINK( ImpTwain, ImplFallbackHdl, void*, pData )
477*cdf0e10cSrcweir {
478*cdf0e10cSrcweir     const ULONG nEvent = (ULONG) pData;
479*cdf0e10cSrcweir     bool        bFallback = true;
480*cdf0e10cSrcweir 
481*cdf0e10cSrcweir     switch( nCurState )
482*cdf0e10cSrcweir     {
483*cdf0e10cSrcweir         case( 7 ):
484*cdf0e10cSrcweir         case( 6 ):
485*cdf0e10cSrcweir         {
486*cdf0e10cSrcweir             TW_PENDINGXFERS aXfers;
487*cdf0e10cSrcweir 
488*cdf0e10cSrcweir             if( PFUNC( &aAppIdent, &aSrcIdent, DG_CONTROL, DAT_PENDINGXFERS, MSG_ENDXFER, &aXfers ) == TWRC_SUCCESS )
489*cdf0e10cSrcweir             {
490*cdf0e10cSrcweir                 if( aXfers.Count != 0 )
491*cdf0e10cSrcweir                     PFUNC( &aAppIdent, &aSrcIdent, DG_CONTROL, DAT_PENDINGXFERS, MSG_RESET, &aXfers );
492*cdf0e10cSrcweir             }
493*cdf0e10cSrcweir 
494*cdf0e10cSrcweir             nCurState = 5;
495*cdf0e10cSrcweir         }
496*cdf0e10cSrcweir         break;
497*cdf0e10cSrcweir 
498*cdf0e10cSrcweir         case( 5 ):
499*cdf0e10cSrcweir         {
500*cdf0e10cSrcweir             TW_USERINTERFACE aUI = { true, true, hTwainWnd };
501*cdf0e10cSrcweir 
502*cdf0e10cSrcweir             PFUNC( &aAppIdent, &aSrcIdent, DG_CONTROL, DAT_USERINTERFACE, MSG_DISABLEDS, &aUI );
503*cdf0e10cSrcweir             nCurState = 4;
504*cdf0e10cSrcweir 
505*cdf0e10cSrcweir             // #107835# deregister as vetoable close listener
506*cdf0e10cSrcweir             ImplDeregisterCloseListener();
507*cdf0e10cSrcweir         }
508*cdf0e10cSrcweir         break;
509*cdf0e10cSrcweir 
510*cdf0e10cSrcweir         case( 4 ):
511*cdf0e10cSrcweir         {
512*cdf0e10cSrcweir             PFUNC( &aAppIdent, NULL, DG_CONTROL, DAT_IDENTITY, MSG_CLOSEDS, &aSrcIdent );
513*cdf0e10cSrcweir             nCurState = 3;
514*cdf0e10cSrcweir         }
515*cdf0e10cSrcweir         break;
516*cdf0e10cSrcweir 
517*cdf0e10cSrcweir         case( 3 ):
518*cdf0e10cSrcweir         {
519*cdf0e10cSrcweir             PFUNC( &aAppIdent, NULL, DG_CONTROL, DAT_PARENT, MSG_CLOSEDSM, &hTwainWnd );
520*cdf0e10cSrcweir             nCurState = 2;
521*cdf0e10cSrcweir         }
522*cdf0e10cSrcweir         break;
523*cdf0e10cSrcweir 
524*cdf0e10cSrcweir         case( 2 ):
525*cdf0e10cSrcweir         {
526*cdf0e10cSrcweir             delete pMod;
527*cdf0e10cSrcweir             pMod = NULL;
528*cdf0e10cSrcweir             nCurState = 1;
529*cdf0e10cSrcweir         }
530*cdf0e10cSrcweir         break;
531*cdf0e10cSrcweir 
532*cdf0e10cSrcweir         default:
533*cdf0e10cSrcweir         {
534*cdf0e10cSrcweir             if( nEvent != TWAIN_EVENT_NONE )
535*cdf0e10cSrcweir                 aNotifyLink.Call( (void*) nEvent );
536*cdf0e10cSrcweir 
537*cdf0e10cSrcweir             bFallback = false;
538*cdf0e10cSrcweir         }
539*cdf0e10cSrcweir         break;
540*cdf0e10cSrcweir     }
541*cdf0e10cSrcweir 
542*cdf0e10cSrcweir     if( bFallback )
543*cdf0e10cSrcweir         ImplFallback( nEvent );
544*cdf0e10cSrcweir 
545*cdf0e10cSrcweir     return 0L;
546*cdf0e10cSrcweir }
547*cdf0e10cSrcweir 
548*cdf0e10cSrcweir // -----------------------------------------------------------------------------
549*cdf0e10cSrcweir 
550*cdf0e10cSrcweir IMPL_LINK( ImpTwain, ImplDestroyHdl, void*, /*p*/ )
551*cdf0e10cSrcweir {
552*cdf0e10cSrcweir     if( hTwainWnd )
553*cdf0e10cSrcweir         DestroyWindow( hTwainWnd );
554*cdf0e10cSrcweir 
555*cdf0e10cSrcweir     if( hTwainHook )
556*cdf0e10cSrcweir         UnhookWindowsHookEx( hTwainHook );
557*cdf0e10cSrcweir 
558*cdf0e10cSrcweir     // #107835# permit destruction of ourselves (normally, refcount
559*cdf0e10cSrcweir     // should drop to zero exactly here)
560*cdf0e10cSrcweir     mxSelfRef = NULL;
561*cdf0e10cSrcweir     pImpTwainInstance = NULL;
562*cdf0e10cSrcweir 
563*cdf0e10cSrcweir     return 0L;
564*cdf0e10cSrcweir }
565*cdf0e10cSrcweir 
566*cdf0e10cSrcweir // -----------------------------------------------------------------------------
567*cdf0e10cSrcweir 
568*cdf0e10cSrcweir uno::Reference< frame::XFrame > ImpTwain::ImplGetActiveFrame()
569*cdf0e10cSrcweir {
570*cdf0e10cSrcweir     try
571*cdf0e10cSrcweir     {
572*cdf0e10cSrcweir         uno::Reference< lang::XMultiServiceFactory >  xMgr( ::comphelper::getProcessServiceFactory() );
573*cdf0e10cSrcweir 
574*cdf0e10cSrcweir         if( xMgr.is() )
575*cdf0e10cSrcweir         {
576*cdf0e10cSrcweir             // query desktop instance
577*cdf0e10cSrcweir             uno::Reference< frame::XDesktop > xDesktop( xMgr->createInstance(
578*cdf0e10cSrcweir                                                             OUString::createFromAscii( "com.sun.star.frame.Desktop" ) ), uno::UNO_QUERY );
579*cdf0e10cSrcweir 
580*cdf0e10cSrcweir             if( xDesktop.is() )
581*cdf0e10cSrcweir             {
582*cdf0e10cSrcweir                 // query property set from desktop, which contains the currently active frame
583*cdf0e10cSrcweir                 uno::Reference< beans::XPropertySet > xDesktopProps( xDesktop, uno::UNO_QUERY );
584*cdf0e10cSrcweir 
585*cdf0e10cSrcweir                 if( xDesktopProps.is() )
586*cdf0e10cSrcweir                 {
587*cdf0e10cSrcweir                     uno::Any aActiveFrame;
588*cdf0e10cSrcweir 
589*cdf0e10cSrcweir                     try
590*cdf0e10cSrcweir                     {
591*cdf0e10cSrcweir                         aActiveFrame = xDesktopProps->getPropertyValue(
592*cdf0e10cSrcweir                             OUString::createFromAscii( "ActiveFrame" ) );
593*cdf0e10cSrcweir                     }
594*cdf0e10cSrcweir                     catch( const beans::UnknownPropertyException& )
595*cdf0e10cSrcweir                     {
596*cdf0e10cSrcweir                         // property unknown.
597*cdf0e10cSrcweir                         DBG_ERROR("ImpTwain::ImplGetActiveFrame: ActiveFrame property unknown, cannot determine active frame!");
598*cdf0e10cSrcweir                         return uno::Reference< frame::XFrame >();
599*cdf0e10cSrcweir                     }
600*cdf0e10cSrcweir 
601*cdf0e10cSrcweir                     uno::Reference< frame::XFrame > xActiveFrame;
602*cdf0e10cSrcweir 
603*cdf0e10cSrcweir                     if( (aActiveFrame >>= xActiveFrame) &&
604*cdf0e10cSrcweir                         xActiveFrame.is() )
605*cdf0e10cSrcweir                     {
606*cdf0e10cSrcweir                         return xActiveFrame;
607*cdf0e10cSrcweir                     }
608*cdf0e10cSrcweir                 }
609*cdf0e10cSrcweir             }
610*cdf0e10cSrcweir         }
611*cdf0e10cSrcweir     }
612*cdf0e10cSrcweir     catch( const uno::Exception& )
613*cdf0e10cSrcweir     {
614*cdf0e10cSrcweir     }
615*cdf0e10cSrcweir 
616*cdf0e10cSrcweir     DBG_ERROR("ImpTwain::ImplGetActiveFrame: Could not determine active frame!");
617*cdf0e10cSrcweir     return uno::Reference< frame::XFrame >();
618*cdf0e10cSrcweir }
619*cdf0e10cSrcweir 
620*cdf0e10cSrcweir // -----------------------------------------------------------------------------
621*cdf0e10cSrcweir 
622*cdf0e10cSrcweir uno::Reference< util::XCloseBroadcaster > ImpTwain::ImplGetActiveFrameCloseBroadcaster()
623*cdf0e10cSrcweir {
624*cdf0e10cSrcweir     try
625*cdf0e10cSrcweir     {
626*cdf0e10cSrcweir         return uno::Reference< util::XCloseBroadcaster >( ImplGetActiveFrame(), uno::UNO_QUERY );
627*cdf0e10cSrcweir     }
628*cdf0e10cSrcweir     catch( const uno::Exception& )
629*cdf0e10cSrcweir     {
630*cdf0e10cSrcweir     }
631*cdf0e10cSrcweir 
632*cdf0e10cSrcweir     DBG_ERROR("ImpTwain::ImplGetActiveFrameCloseBroadcaster: Could determine close broadcaster on active frame!");
633*cdf0e10cSrcweir     return uno::Reference< util::XCloseBroadcaster >();
634*cdf0e10cSrcweir }
635*cdf0e10cSrcweir 
636*cdf0e10cSrcweir // -----------------------------------------------------------------------------
637*cdf0e10cSrcweir 
638*cdf0e10cSrcweir void ImpTwain::ImplRegisterCloseListener()
639*cdf0e10cSrcweir {
640*cdf0e10cSrcweir     try
641*cdf0e10cSrcweir     {
642*cdf0e10cSrcweir         uno::Reference< util::XCloseBroadcaster > xCloseBroadcaster( ImplGetActiveFrameCloseBroadcaster() );
643*cdf0e10cSrcweir 
644*cdf0e10cSrcweir         if( xCloseBroadcaster.is() )
645*cdf0e10cSrcweir         {
646*cdf0e10cSrcweir             xCloseBroadcaster->addCloseListener(this);
647*cdf0e10cSrcweir             return; // successfully registered as a close listener
648*cdf0e10cSrcweir         }
649*cdf0e10cSrcweir         else
650*cdf0e10cSrcweir         {
651*cdf0e10cSrcweir             // interface unknown. don't register, then
652*cdf0e10cSrcweir             DBG_ERROR("ImpTwain::ImplRegisterCloseListener: XFrame has no XCloseBroadcaster!");
653*cdf0e10cSrcweir             return;
654*cdf0e10cSrcweir         }
655*cdf0e10cSrcweir     }
656*cdf0e10cSrcweir     catch( const uno::Exception& )
657*cdf0e10cSrcweir     {
658*cdf0e10cSrcweir     }
659*cdf0e10cSrcweir 
660*cdf0e10cSrcweir     DBG_ERROR("ImpTwain::ImplRegisterCloseListener: Could not register as close listener!");
661*cdf0e10cSrcweir }
662*cdf0e10cSrcweir 
663*cdf0e10cSrcweir // -----------------------------------------------------------------------------
664*cdf0e10cSrcweir 
665*cdf0e10cSrcweir void ImpTwain::ImplDeregisterCloseListener()
666*cdf0e10cSrcweir {
667*cdf0e10cSrcweir     try
668*cdf0e10cSrcweir     {
669*cdf0e10cSrcweir         uno::Reference< util::XCloseBroadcaster > xCloseBroadcaster(
670*cdf0e10cSrcweir             ImplGetActiveFrameCloseBroadcaster() );
671*cdf0e10cSrcweir 
672*cdf0e10cSrcweir         if( xCloseBroadcaster.is() )
673*cdf0e10cSrcweir         {
674*cdf0e10cSrcweir             xCloseBroadcaster->removeCloseListener(this);
675*cdf0e10cSrcweir             return; // successfully deregistered as a close listener
676*cdf0e10cSrcweir         }
677*cdf0e10cSrcweir         else
678*cdf0e10cSrcweir         {
679*cdf0e10cSrcweir             // interface unknown. don't deregister, then
680*cdf0e10cSrcweir             DBG_ERROR("ImpTwain::ImplDeregisterCloseListener: XFrame has no XCloseBroadcaster!");
681*cdf0e10cSrcweir             return;
682*cdf0e10cSrcweir         }
683*cdf0e10cSrcweir     }
684*cdf0e10cSrcweir     catch( const uno::Exception& )
685*cdf0e10cSrcweir     {
686*cdf0e10cSrcweir     }
687*cdf0e10cSrcweir 
688*cdf0e10cSrcweir     DBG_ERROR("ImpTwain::ImplDeregisterCloseListener: Could not deregister as close listener!");
689*cdf0e10cSrcweir }
690*cdf0e10cSrcweir 
691*cdf0e10cSrcweir // -----------------------------------------------------------------------------
692*cdf0e10cSrcweir 
693*cdf0e10cSrcweir void SAL_CALL ImpTwain::queryClosing( const lang::EventObject& /*Source*/, sal_Bool GetsOwnership ) throw (util::CloseVetoException, uno::RuntimeException)
694*cdf0e10cSrcweir {
695*cdf0e10cSrcweir     // shall we re-send the close query later on?
696*cdf0e10cSrcweir     mbCloseFrameOnExit = GetsOwnership;
697*cdf0e10cSrcweir 
698*cdf0e10cSrcweir     // the sole purpose of this listener is to forbid closing of the listened-at frame
699*cdf0e10cSrcweir     throw util::CloseVetoException();
700*cdf0e10cSrcweir }
701*cdf0e10cSrcweir 
702*cdf0e10cSrcweir // -----------------------------------------------------------------------------
703*cdf0e10cSrcweir 
704*cdf0e10cSrcweir void SAL_CALL ImpTwain::notifyClosing( const lang::EventObject& /*Source*/ ) throw (uno::RuntimeException)
705*cdf0e10cSrcweir {
706*cdf0e10cSrcweir     // should not happen
707*cdf0e10cSrcweir     DBG_ERROR("ImpTwain::notifyClosing called, but we vetoed the closing before!");
708*cdf0e10cSrcweir }
709*cdf0e10cSrcweir 
710*cdf0e10cSrcweir // -----------------------------------------------------------------------------
711*cdf0e10cSrcweir 
712*cdf0e10cSrcweir void SAL_CALL ImpTwain::disposing( const lang::EventObject& /*Source*/ ) throw (uno::RuntimeException)
713*cdf0e10cSrcweir {
714*cdf0e10cSrcweir     // we're not holding any references to the frame, thus noop
715*cdf0e10cSrcweir }
716*cdf0e10cSrcweir 
717*cdf0e10cSrcweir // -----------------------------------------------------------------------------
718*cdf0e10cSrcweir 
719*cdf0e10cSrcweir void ImpTwain::ImplSendCloseEvent()
720*cdf0e10cSrcweir {
721*cdf0e10cSrcweir     try
722*cdf0e10cSrcweir     {
723*cdf0e10cSrcweir         uno::Reference< util::XCloseable > xCloseable( ImplGetActiveFrame(), uno::UNO_QUERY );
724*cdf0e10cSrcweir 
725*cdf0e10cSrcweir         if( xCloseable.is() )
726*cdf0e10cSrcweir             xCloseable->close( true );
727*cdf0e10cSrcweir     }
728*cdf0e10cSrcweir     catch( const uno::Exception& )
729*cdf0e10cSrcweir     {
730*cdf0e10cSrcweir     }
731*cdf0e10cSrcweir 
732*cdf0e10cSrcweir     DBG_ERROR("ImpTwain::ImplSendCloseEvent: Could not send required close broadcast!");
733*cdf0e10cSrcweir }
734*cdf0e10cSrcweir 
735*cdf0e10cSrcweir 
736*cdf0e10cSrcweir // ---------
737*cdf0e10cSrcweir // - Twain -
738*cdf0e10cSrcweir // ---------
739*cdf0e10cSrcweir 
740*cdf0e10cSrcweir class Twain
741*cdf0e10cSrcweir {
742*cdf0e10cSrcweir     uno::Reference< lang::XEventListener >      mxListener;
743*cdf0e10cSrcweir     uno::Reference< scanner::XScannerManager >  mxMgr;
744*cdf0e10cSrcweir     const ScannerManager*                       mpCurMgr;
745*cdf0e10cSrcweir     ImpTwain*                                   mpImpTwain;
746*cdf0e10cSrcweir     TwainState                                  meState;
747*cdf0e10cSrcweir 
748*cdf0e10cSrcweir                                                 DECL_LINK( ImpNotifyHdl, ImpTwain* );
749*cdf0e10cSrcweir 
750*cdf0e10cSrcweir public:
751*cdf0e10cSrcweir 
752*cdf0e10cSrcweir                                     Twain();
753*cdf0e10cSrcweir                                     ~Twain();
754*cdf0e10cSrcweir 
755*cdf0e10cSrcweir     bool                            SelectSource( ScannerManager& rMgr );
756*cdf0e10cSrcweir     bool                            PerformTransfer( ScannerManager& rMgr, const uno::Reference< lang::XEventListener >& rxListener );
757*cdf0e10cSrcweir 
758*cdf0e10cSrcweir     TwainState                      GetState() const { return meState; }
759*cdf0e10cSrcweir };
760*cdf0e10cSrcweir 
761*cdf0e10cSrcweir // ------------------------------------------------------------------------
762*cdf0e10cSrcweir 
763*cdf0e10cSrcweir Twain::Twain() :
764*cdf0e10cSrcweir         mpCurMgr( NULL ),
765*cdf0e10cSrcweir         mpImpTwain( NULL ),
766*cdf0e10cSrcweir         meState( TWAIN_STATE_NONE )
767*cdf0e10cSrcweir {
768*cdf0e10cSrcweir }
769*cdf0e10cSrcweir 
770*cdf0e10cSrcweir // ------------------------------------------------------------------------
771*cdf0e10cSrcweir 
772*cdf0e10cSrcweir Twain::~Twain()
773*cdf0e10cSrcweir {
774*cdf0e10cSrcweir     if( mpImpTwain )
775*cdf0e10cSrcweir         mpImpTwain->Destroy();
776*cdf0e10cSrcweir }
777*cdf0e10cSrcweir 
778*cdf0e10cSrcweir // ------------------------------------------------------------------------
779*cdf0e10cSrcweir 
780*cdf0e10cSrcweir bool Twain::SelectSource( ScannerManager& rMgr )
781*cdf0e10cSrcweir {
782*cdf0e10cSrcweir     bool bRet;
783*cdf0e10cSrcweir 
784*cdf0e10cSrcweir     if( !mpImpTwain )
785*cdf0e10cSrcweir     {
786*cdf0e10cSrcweir         // #107835# hold reference to ScannerManager, to prevent premature death
787*cdf0e10cSrcweir         mxMgr = uno::Reference< scanner::XScannerManager >( static_cast< OWeakObject* >( const_cast< ScannerManager* >( mpCurMgr = &rMgr ) ),
788*cdf0e10cSrcweir                                                             uno::UNO_QUERY ),
789*cdf0e10cSrcweir 
790*cdf0e10cSrcweir         meState = TWAIN_STATE_NONE;
791*cdf0e10cSrcweir         mpImpTwain = new ImpTwain( rMgr, LINK( this, Twain, ImpNotifyHdl ) );
792*cdf0e10cSrcweir         bRet = mpImpTwain->SelectSource();
793*cdf0e10cSrcweir     }
794*cdf0e10cSrcweir     else
795*cdf0e10cSrcweir         bRet = false;
796*cdf0e10cSrcweir 
797*cdf0e10cSrcweir     return bRet;
798*cdf0e10cSrcweir }
799*cdf0e10cSrcweir 
800*cdf0e10cSrcweir // ------------------------------------------------------------------------
801*cdf0e10cSrcweir 
802*cdf0e10cSrcweir bool Twain::PerformTransfer( ScannerManager& rMgr, const uno::Reference< lang::XEventListener >& rxListener )
803*cdf0e10cSrcweir {
804*cdf0e10cSrcweir     bool bRet;
805*cdf0e10cSrcweir 
806*cdf0e10cSrcweir     if( !mpImpTwain )
807*cdf0e10cSrcweir     {
808*cdf0e10cSrcweir         // #107835# hold reference to ScannerManager, to prevent premature death
809*cdf0e10cSrcweir         mxMgr = uno::Reference< scanner::XScannerManager >( static_cast< OWeakObject* >( const_cast< ScannerManager* >( mpCurMgr = &rMgr ) ),
810*cdf0e10cSrcweir                                                             uno::UNO_QUERY ),
811*cdf0e10cSrcweir 
812*cdf0e10cSrcweir         mxListener = rxListener;
813*cdf0e10cSrcweir         meState = TWAIN_STATE_NONE;
814*cdf0e10cSrcweir         mpImpTwain = new ImpTwain( rMgr, LINK( this, Twain, ImpNotifyHdl ) );
815*cdf0e10cSrcweir         bRet = mpImpTwain->InitXfer();
816*cdf0e10cSrcweir     }
817*cdf0e10cSrcweir     else
818*cdf0e10cSrcweir         bRet = false;
819*cdf0e10cSrcweir 
820*cdf0e10cSrcweir     return bRet;
821*cdf0e10cSrcweir }
822*cdf0e10cSrcweir 
823*cdf0e10cSrcweir // ------------------------------------------------------------------------
824*cdf0e10cSrcweir 
825*cdf0e10cSrcweir IMPL_LINK( Twain, ImpNotifyHdl, ImpTwain*, nEvent )
826*cdf0e10cSrcweir {
827*cdf0e10cSrcweir     switch( (ULONG)(void*) nEvent )
828*cdf0e10cSrcweir     {
829*cdf0e10cSrcweir         case( TWAIN_EVENT_SCANNING ):
830*cdf0e10cSrcweir             meState = TWAIN_STATE_SCANNING;
831*cdf0e10cSrcweir         break;
832*cdf0e10cSrcweir 
833*cdf0e10cSrcweir         case( TWAIN_EVENT_QUIT ):
834*cdf0e10cSrcweir         {
835*cdf0e10cSrcweir             if( meState != TWAIN_STATE_DONE )
836*cdf0e10cSrcweir                 meState = TWAIN_STATE_CANCELED;
837*cdf0e10cSrcweir 
838*cdf0e10cSrcweir             if( mpImpTwain )
839*cdf0e10cSrcweir             {
840*cdf0e10cSrcweir                 mpImpTwain->Destroy();
841*cdf0e10cSrcweir                 mpImpTwain = NULL;
842*cdf0e10cSrcweir                 mpCurMgr = NULL;
843*cdf0e10cSrcweir             }
844*cdf0e10cSrcweir 
845*cdf0e10cSrcweir             if( mxListener.is() )
846*cdf0e10cSrcweir                 mxListener->disposing( lang::EventObject( mxMgr ) );
847*cdf0e10cSrcweir 
848*cdf0e10cSrcweir             mxListener = NULL;
849*cdf0e10cSrcweir         }
850*cdf0e10cSrcweir         break;
851*cdf0e10cSrcweir 
852*cdf0e10cSrcweir         case( TWAIN_EVENT_XFER ):
853*cdf0e10cSrcweir         {
854*cdf0e10cSrcweir             if( mpImpTwain )
855*cdf0e10cSrcweir             {
856*cdf0e10cSrcweir                 meState = ( mpCurMgr->GetData() ? TWAIN_STATE_DONE : TWAIN_STATE_CANCELED );
857*cdf0e10cSrcweir 
858*cdf0e10cSrcweir                 mpImpTwain->Destroy();
859*cdf0e10cSrcweir                 mpImpTwain = NULL;
860*cdf0e10cSrcweir                 mpCurMgr = NULL;
861*cdf0e10cSrcweir 
862*cdf0e10cSrcweir                 if( mxListener.is() )
863*cdf0e10cSrcweir                     mxListener->disposing( lang::EventObject( mxMgr ) );
864*cdf0e10cSrcweir             }
865*cdf0e10cSrcweir 
866*cdf0e10cSrcweir             mxListener = NULL;
867*cdf0e10cSrcweir         }
868*cdf0e10cSrcweir         break;
869*cdf0e10cSrcweir 
870*cdf0e10cSrcweir         default:
871*cdf0e10cSrcweir         break;
872*cdf0e10cSrcweir     }
873*cdf0e10cSrcweir 
874*cdf0e10cSrcweir     return 0L;
875*cdf0e10cSrcweir }
876*cdf0e10cSrcweir 
877*cdf0e10cSrcweir // -----------
878*cdf0e10cSrcweir // - statics -
879*cdf0e10cSrcweir // -----------
880*cdf0e10cSrcweir 
881*cdf0e10cSrcweir static Twain aTwain;
882*cdf0e10cSrcweir 
883*cdf0e10cSrcweir // ------------------
884*cdf0e10cSrcweir // - ScannerManager -
885*cdf0e10cSrcweir // ------------------
886*cdf0e10cSrcweir 
887*cdf0e10cSrcweir void ScannerManager::AcquireData()
888*cdf0e10cSrcweir {
889*cdf0e10cSrcweir }
890*cdf0e10cSrcweir 
891*cdf0e10cSrcweir void ScannerManager::ReleaseData()
892*cdf0e10cSrcweir {
893*cdf0e10cSrcweir     if( mpData )
894*cdf0e10cSrcweir     {
895*cdf0e10cSrcweir         GlobalFree( (HGLOBAL)(long) mpData );
896*cdf0e10cSrcweir         mpData = NULL;
897*cdf0e10cSrcweir     }
898*cdf0e10cSrcweir }
899*cdf0e10cSrcweir 
900*cdf0e10cSrcweir // -----------------------------------------------------------------------------
901*cdf0e10cSrcweir 
902*cdf0e10cSrcweir AWT::Size ScannerManager::getSize() throw()
903*cdf0e10cSrcweir {
904*cdf0e10cSrcweir     AWT::Size   aRet;
905*cdf0e10cSrcweir     HGLOBAL     hDIB = (HGLOBAL)(long) mpData;
906*cdf0e10cSrcweir 
907*cdf0e10cSrcweir     if( hDIB )
908*cdf0e10cSrcweir     {
909*cdf0e10cSrcweir         BITMAPINFOHEADER* pBIH = (BITMAPINFOHEADER*) GlobalLock( hDIB );
910*cdf0e10cSrcweir 
911*cdf0e10cSrcweir         if( pBIH )
912*cdf0e10cSrcweir         {
913*cdf0e10cSrcweir             aRet.Width = pBIH->biWidth;
914*cdf0e10cSrcweir             aRet.Height = pBIH->biHeight;
915*cdf0e10cSrcweir         }
916*cdf0e10cSrcweir         else
917*cdf0e10cSrcweir             aRet.Width = aRet.Height = 0;
918*cdf0e10cSrcweir 
919*cdf0e10cSrcweir         GlobalUnlock( hDIB );
920*cdf0e10cSrcweir     }
921*cdf0e10cSrcweir     else
922*cdf0e10cSrcweir         aRet.Width = aRet.Height = 0;
923*cdf0e10cSrcweir 
924*cdf0e10cSrcweir     return aRet;
925*cdf0e10cSrcweir }
926*cdf0e10cSrcweir 
927*cdf0e10cSrcweir // -----------------------------------------------------------------------------
928*cdf0e10cSrcweir 
929*cdf0e10cSrcweir SEQ( sal_Int8 ) ScannerManager::getDIB() throw()
930*cdf0e10cSrcweir {
931*cdf0e10cSrcweir     SEQ( sal_Int8 ) aRet;
932*cdf0e10cSrcweir 
933*cdf0e10cSrcweir     if( mpData )
934*cdf0e10cSrcweir     {
935*cdf0e10cSrcweir         HGLOBAL             hDIB = (HGLOBAL)(long) mpData;
936*cdf0e10cSrcweir         const sal_uInt32    nDIBSize = GlobalSize( hDIB );
937*cdf0e10cSrcweir         BITMAPINFOHEADER*   pBIH = (BITMAPINFOHEADER*) GlobalLock( hDIB );
938*cdf0e10cSrcweir 
939*cdf0e10cSrcweir         if( pBIH )
940*cdf0e10cSrcweir         {
941*cdf0e10cSrcweir             sal_uInt32  nColEntries;
942*cdf0e10cSrcweir 
943*cdf0e10cSrcweir             switch( pBIH->biBitCount )
944*cdf0e10cSrcweir             {
945*cdf0e10cSrcweir                 case( 1 ):
946*cdf0e10cSrcweir                 case( 4 ):
947*cdf0e10cSrcweir                 case( 8 ):
948*cdf0e10cSrcweir                     nColEntries = pBIH->biClrUsed ? pBIH->biClrUsed : ( 1 << pBIH->biBitCount );
949*cdf0e10cSrcweir                 break;
950*cdf0e10cSrcweir 
951*cdf0e10cSrcweir                 case( 24 ):
952*cdf0e10cSrcweir                     nColEntries = pBIH->biClrUsed ? pBIH->biClrUsed : 0;
953*cdf0e10cSrcweir                 break;
954*cdf0e10cSrcweir 
955*cdf0e10cSrcweir                 case( 16 ):
956*cdf0e10cSrcweir                 case( 32 ):
957*cdf0e10cSrcweir                 {
958*cdf0e10cSrcweir                     nColEntries = pBIH->biClrUsed;
959*cdf0e10cSrcweir 
960*cdf0e10cSrcweir                     if( pBIH->biCompression == BI_BITFIELDS )
961*cdf0e10cSrcweir                         nColEntries += 3;
962*cdf0e10cSrcweir                 }
963*cdf0e10cSrcweir                 break;
964*cdf0e10cSrcweir 
965*cdf0e10cSrcweir                 default:
966*cdf0e10cSrcweir                     nColEntries = 0;
967*cdf0e10cSrcweir                 break;
968*cdf0e10cSrcweir             }
969*cdf0e10cSrcweir 
970*cdf0e10cSrcweir             aRet = SEQ( sal_Int8 )( sizeof( BITMAPFILEHEADER ) + nDIBSize );
971*cdf0e10cSrcweir 
972*cdf0e10cSrcweir             sal_Int8*       pBuf = aRet.getArray();
973*cdf0e10cSrcweir             SvMemoryStream* pMemStm = new SvMemoryStream( (char*) pBuf, sizeof( BITMAPFILEHEADER ), STREAM_WRITE );
974*cdf0e10cSrcweir 
975*cdf0e10cSrcweir             *pMemStm << 'B' << 'M' << (sal_uInt32) 0 << (sal_uInt32) 0;
976*cdf0e10cSrcweir             *pMemStm << (sal_uInt32) ( sizeof( BITMAPFILEHEADER ) + pBIH->biSize + ( nColEntries * sizeof( RGBQUAD ) ) );
977*cdf0e10cSrcweir 
978*cdf0e10cSrcweir             delete pMemStm;
979*cdf0e10cSrcweir             memcpy( pBuf + sizeof( BITMAPFILEHEADER ), pBIH, nDIBSize );
980*cdf0e10cSrcweir         }
981*cdf0e10cSrcweir 
982*cdf0e10cSrcweir         GlobalUnlock( hDIB );
983*cdf0e10cSrcweir         ReleaseData();
984*cdf0e10cSrcweir     }
985*cdf0e10cSrcweir 
986*cdf0e10cSrcweir     return aRet;
987*cdf0e10cSrcweir }
988*cdf0e10cSrcweir 
989*cdf0e10cSrcweir // -----------------------------------------------------------------------------
990*cdf0e10cSrcweir 
991*cdf0e10cSrcweir SEQ( ScannerContext ) SAL_CALL ScannerManager::getAvailableScanners() throw()
992*cdf0e10cSrcweir {
993*cdf0e10cSrcweir     vos::OGuard             aGuard( maProtector );
994*cdf0e10cSrcweir     SEQ( ScannerContext )   aRet( 1 );
995*cdf0e10cSrcweir 
996*cdf0e10cSrcweir     aRet.getArray()[0].ScannerName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "TWAIN" ) );
997*cdf0e10cSrcweir     aRet.getArray()[0].InternalData = 0;
998*cdf0e10cSrcweir 
999*cdf0e10cSrcweir     return aRet;
1000*cdf0e10cSrcweir }
1001*cdf0e10cSrcweir 
1002*cdf0e10cSrcweir // -----------------------------------------------------------------------------
1003*cdf0e10cSrcweir 
1004*cdf0e10cSrcweir sal_Bool SAL_CALL ScannerManager::configureScanner( ScannerContext& rContext )
1005*cdf0e10cSrcweir     throw( ScannerException )
1006*cdf0e10cSrcweir {
1007*cdf0e10cSrcweir     vos::OGuard                         aGuard( maProtector );
1008*cdf0e10cSrcweir     uno::Reference< XScannerManager >   xThis( this );
1009*cdf0e10cSrcweir 
1010*cdf0e10cSrcweir     if( rContext.InternalData != 0 || rContext.ScannerName != ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "TWAIN" ) ) )
1011*cdf0e10cSrcweir         throw ScannerException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Scanner does not exist" ) ), xThis, ScanError_InvalidContext );
1012*cdf0e10cSrcweir 
1013*cdf0e10cSrcweir     ReleaseData();
1014*cdf0e10cSrcweir 
1015*cdf0e10cSrcweir     return aTwain.SelectSource( *this );
1016*cdf0e10cSrcweir }
1017*cdf0e10cSrcweir 
1018*cdf0e10cSrcweir // -----------------------------------------------------------------------------
1019*cdf0e10cSrcweir 
1020*cdf0e10cSrcweir void SAL_CALL ScannerManager::startScan( const ScannerContext& rContext, const uno::Reference< lang::XEventListener >& rxListener )
1021*cdf0e10cSrcweir     throw( ScannerException )
1022*cdf0e10cSrcweir {
1023*cdf0e10cSrcweir     vos::OGuard                         aGuard( maProtector );
1024*cdf0e10cSrcweir     uno::Reference< XScannerManager >   xThis( this );
1025*cdf0e10cSrcweir 
1026*cdf0e10cSrcweir     if( rContext.InternalData != 0 || rContext.ScannerName != ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "TWAIN" ) ) )
1027*cdf0e10cSrcweir         throw ScannerException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Scanner does not exist" ) ), xThis, ScanError_InvalidContext );
1028*cdf0e10cSrcweir 
1029*cdf0e10cSrcweir     ReleaseData();
1030*cdf0e10cSrcweir     aTwain.PerformTransfer( *this, rxListener );
1031*cdf0e10cSrcweir }
1032*cdf0e10cSrcweir 
1033*cdf0e10cSrcweir // -----------------------------------------------------------------------------
1034*cdf0e10cSrcweir 
1035*cdf0e10cSrcweir ScanError SAL_CALL ScannerManager::getError( const ScannerContext& rContext )
1036*cdf0e10cSrcweir     throw( ScannerException )
1037*cdf0e10cSrcweir {
1038*cdf0e10cSrcweir     vos::OGuard                         aGuard( maProtector );
1039*cdf0e10cSrcweir     uno::Reference< XScannerManager >   xThis( this );
1040*cdf0e10cSrcweir 
1041*cdf0e10cSrcweir     if( rContext.InternalData != 0 || rContext.ScannerName != ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "TWAIN" ) ) )
1042*cdf0e10cSrcweir         throw ScannerException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Scanner does not exist" ) ), xThis, ScanError_InvalidContext );
1043*cdf0e10cSrcweir 
1044*cdf0e10cSrcweir     return( ( aTwain.GetState() == TWAIN_STATE_CANCELED ) ? ScanError_ScanCanceled : ScanError_ScanErrorNone );
1045*cdf0e10cSrcweir }
1046*cdf0e10cSrcweir 
1047*cdf0e10cSrcweir // -----------------------------------------------------------------------------
1048*cdf0e10cSrcweir 
1049*cdf0e10cSrcweir uno::Reference< awt::XBitmap > SAL_CALL ScannerManager::getBitmap( const ScannerContext& /*rContext*/ )
1050*cdf0e10cSrcweir     throw( ScannerException )
1051*cdf0e10cSrcweir {
1052*cdf0e10cSrcweir     vos::OGuard aGuard( maProtector );
1053*cdf0e10cSrcweir     return uno::Reference< awt::XBitmap >( this );
1054*cdf0e10cSrcweir }
1055