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