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 10cdf0e10cSrcweir * 11*2a97ec55SAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0 12cdf0e10cSrcweir * 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. 19cdf0e10cSrcweir * 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 153cdf0e10cSrcweir LRESULT CALLBACK TwainWndProc( HWND hWnd,UINT nMsg, WPARAM nPar1, LPARAM nPar2 ) 154cdf0e10cSrcweir { 155cdf0e10cSrcweir return DefWindowProc( hWnd, nMsg, nPar1, nPar2 ); 156cdf0e10cSrcweir } 157cdf0e10cSrcweir 158cdf0e10cSrcweir // ------------------------------------------------------------------------- 159cdf0e10cSrcweir 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 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 223cdf0e10cSrcweir ImpTwain::~ImpTwain() 224cdf0e10cSrcweir { 225cdf0e10cSrcweir // are we responsible for application shutdown? 226cdf0e10cSrcweir if( mbCloseFrameOnExit ) 227cdf0e10cSrcweir ImplSendCloseEvent(); 228cdf0e10cSrcweir } 229cdf0e10cSrcweir 230cdf0e10cSrcweir // ----------------------------------------------------------------------------- 231cdf0e10cSrcweir 232cdf0e10cSrcweir void ImpTwain::Destroy() 233cdf0e10cSrcweir { 234cdf0e10cSrcweir ImplFallback( TWAIN_EVENT_NONE ); 235cdf0e10cSrcweir Application::PostUserEvent( LINK( this, ImpTwain, ImplDestroyHdl ), NULL ); 236cdf0e10cSrcweir } 237cdf0e10cSrcweir 238cdf0e10cSrcweir // ----------------------------------------------------------------------------- 239cdf0e10cSrcweir 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 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 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 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 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 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 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 465cdf0e10cSrcweir void ImpTwain::ImplFallback( ULONG nEvent ) 466cdf0e10cSrcweir { 467cdf0e10cSrcweir Application::PostUserEvent( LINK( this, ImpTwain, ImplFallbackHdl ), (void*) nEvent ); 468cdf0e10cSrcweir } 469cdf0e10cSrcweir 470cdf0e10cSrcweir // ----------------------------------------------------------------------------- 471cdf0e10cSrcweir 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 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 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 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 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 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 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 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 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 754cdf0e10cSrcweir TwainState GetState() const { return meState; } 755cdf0e10cSrcweir }; 756cdf0e10cSrcweir 757cdf0e10cSrcweir // ------------------------------------------------------------------------ 758cdf0e10cSrcweir 759cdf0e10cSrcweir Twain::Twain() : 760cdf0e10cSrcweir mpCurMgr( NULL ), 761cdf0e10cSrcweir mpImpTwain( NULL ), 762cdf0e10cSrcweir meState( TWAIN_STATE_NONE ) 763cdf0e10cSrcweir { 764cdf0e10cSrcweir } 765cdf0e10cSrcweir 766cdf0e10cSrcweir // ------------------------------------------------------------------------ 767cdf0e10cSrcweir 768cdf0e10cSrcweir Twain::~Twain() 769cdf0e10cSrcweir { 770cdf0e10cSrcweir if( mpImpTwain ) 771cdf0e10cSrcweir mpImpTwain->Destroy(); 772cdf0e10cSrcweir } 773cdf0e10cSrcweir 774cdf0e10cSrcweir // ------------------------------------------------------------------------ 775cdf0e10cSrcweir 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 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 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 883cdf0e10cSrcweir void ScannerManager::AcquireData() 884cdf0e10cSrcweir { 885cdf0e10cSrcweir } 886cdf0e10cSrcweir 887cdf0e10cSrcweir void ScannerManager::ReleaseData() 888cdf0e10cSrcweir { 889cdf0e10cSrcweir if( mpData ) 890cdf0e10cSrcweir { 891cdf0e10cSrcweir GlobalFree( (HGLOBAL)(long) mpData ); 892cdf0e10cSrcweir mpData = NULL; 893cdf0e10cSrcweir } 894cdf0e10cSrcweir } 895cdf0e10cSrcweir 896cdf0e10cSrcweir // ----------------------------------------------------------------------------- 897cdf0e10cSrcweir 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 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 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 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 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 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 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