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