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