00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037 #include "precompiled_extensions.hxx"
00038
00039 #ifndef _COM_SUN_STAR_UNO_ANY_HXX_
00040 #include <com/sun/star/uno/Any.hxx>
00041 #endif
00042
00043 #ifndef _COM_SUN_STAR_UNO_REFERENCE_HXX_
00044 #include <com/sun/star/uno/Reference.hxx>
00045 #endif
00046
00047 #ifndef _COM_SUN_STAR_UTIL_XCLOSEABLE_HPP_
00048 #include <com/sun/star/util/XCloseable.hpp>
00049 #endif
00050
00051 #ifndef _COM_SUN_STAR_UTIL_XCLOSEBROADCASTER_HPP_
00052 #include <com/sun/star/util/XCloseBroadcaster.hpp>
00053 #endif
00054
00055 #ifndef _COM_SUN_STAR_UTIL_XCLOSELISTENER_HPP_
00056 #include <com/sun/star/util/XCloseListener.hpp>
00057 #endif
00058
00059 #ifndef _COM_SUN_STAR_FRAME_XFRAME_HPP_
00060 #include <com/sun/star/frame/XFrame.hpp>
00061 #endif
00062
00063 #ifndef _COM_SUN_STAR_FRAME_XDESKTOP_HPP_
00064 #include <com/sun/star/frame/XDesktop.hpp>
00065 #endif
00066
00067 #ifndef _COM_SUN_STAR_BEANS_XPROPERTYSET_HPP_
00068 #include <com/sun/star/beans/XPropertySet.hpp>
00069 #endif
00070
00071 #ifndef _CPPUHELPER_IMPLBASE1_HXX_
00072 #include <cppuhelper/implbase1.hxx>
00073 #endif
00074
00075 #ifndef _COMPHELPER_PROCESSFACTORY_HXX_
00076 #include <comphelper/processfactory.hxx>
00077 #endif
00078
00079 #include <math.h>
00080 #include <tools/svwin.h>
00081 #include <tools/stream.hxx>
00082 #include <vos/mutex.hxx>
00083 #include <vos/module.hxx>
00084 #include <vcl/svapp.hxx>
00085 #include <vcl/wrkwin.hxx>
00086 #include <vcl/sysdata.hxx>
00087 #include <vcl/salbtype.hxx>
00088 #include "scanner.hxx"
00089
00090 #pragma warning (push,1)
00091 #pragma warning (disable:4668)
00092 #include "twain/twain.h"
00093 #pragma warning (pop)
00094
00095 using namespace ::com::sun::star;
00096
00097
00098
00099
00100
00101 #define TWAIN_SELECT 0x00000001UL
00102 #define TWAIN_ACQUIRE 0x00000002UL
00103 #define TWAIN_TERMINATE 0xFFFFFFFFUL
00104
00105 #define TWAIN_EVENT_NONE 0x00000000UL
00106 #define TWAIN_EVENT_QUIT 0x00000001UL
00107 #define TWAIN_EVENT_SCANNING 0x00000002UL
00108 #define TWAIN_EVENT_XFER 0x00000004UL
00109
00110 #define PFUNC (*pDSM)
00111 #define PTWAINMSG MSG*
00112 #define FIXTODOUBLE( nFix ) ((double)nFix.Whole+(double)nFix.Frac/65536.)
00113 #define FIXTOLONG( nFix ) ((long)floor(FIXTODOUBLE(nFix)+0.5))
00114
00115 #if defined WIN
00116 #define TWAIN_LIBNAME "TWAIN.DLL"
00117 #define TWAIN_FUNCNAME "DSM_Entry"
00118 #elif defined WNT
00119 #define TWAIN_LIBNAME "TWAIN_32.DLL"
00120 #define TWAIN_FUNCNAME "DSM_Entry"
00121 #endif
00122
00123
00124
00125
00126
00127 enum TwainState
00128 {
00129 TWAIN_STATE_NONE = 0,
00130 TWAIN_STATE_SCANNING = 1,
00131 TWAIN_STATE_DONE = 2,
00132 TWAIN_STATE_CANCELED = 3
00133 };
00134
00135
00136
00137
00138
00139 class ImpTwain : public ::cppu::WeakImplHelper1< util::XCloseListener >
00140 {
00141 friend LRESULT CALLBACK TwainMsgProc( int nCode, WPARAM wParam, LPARAM lParam );
00142
00143 uno::Reference< uno::XInterface > mxSelfRef;
00144 uno::Reference< scanner::XScannerManager > mxMgr;
00145 ScannerManager& mrMgr;
00146 TW_IDENTITY aAppIdent;
00147 TW_IDENTITY aSrcIdent;
00148 Link aNotifyLink;
00149 DSMENTRYPROC pDSM;
00150 NAMESPACE_VOS( OModule )* pMod;
00151 ULONG nCurState;
00152 HWND hTwainWnd;
00153 HHOOK hTwainHook;
00154 bool mbCloseFrameOnExit;
00155
00156 bool ImplHandleMsg( void* pMsg );
00157 void ImplCreate();
00158 void ImplOpenSourceManager();
00159 void ImplOpenSource();
00160 bool ImplEnableSource();
00161 void ImplXfer();
00162 void ImplFallback( ULONG nEvent );
00163 void ImplSendCloseEvent();
00164 void ImplDeregisterCloseListener();
00165 void ImplRegisterCloseListener();
00166 uno::Reference< frame::XFrame > ImplGetActiveFrame();
00167 uno::Reference< util::XCloseBroadcaster > ImplGetActiveFrameCloseBroadcaster();
00168
00169 DECL_LINK( ImplFallbackHdl, void* );
00170 DECL_LINK( ImplDestroyHdl, void* );
00171
00172
00173 virtual void SAL_CALL queryClosing( const lang::EventObject& Source, sal_Bool GetsOwnership ) throw (util::CloseVetoException, uno::RuntimeException);
00174 virtual void SAL_CALL notifyClosing( const lang::EventObject& Source ) throw (uno::RuntimeException);
00175
00176
00177 virtual void SAL_CALL disposing( const lang::EventObject& Source ) throw (uno::RuntimeException);
00178
00179 public:
00180
00181 ImpTwain( ScannerManager& rMgr, const Link& rNotifyLink );
00182 ~ImpTwain();
00183
00184 void Destroy();
00185
00186 bool SelectSource();
00187 bool InitXfer();
00188 };
00189
00190
00191
00192
00193
00194 static ImpTwain* pImpTwainInstance = NULL;
00195
00196
00197
00198 LRESULT CALLBACK TwainWndProc( HWND hWnd,UINT nMsg, WPARAM nPar1, LPARAM nPar2 )
00199 {
00200 return DefWindowProc( hWnd, nMsg, nPar1, nPar2 );
00201 }
00202
00203
00204
00205 LRESULT CALLBACK TwainMsgProc( int nCode, WPARAM wParam, LPARAM lParam )
00206 {
00207 MSG* pMsg = (MSG*) lParam;
00208
00209 if( ( nCode < 0 ) || ( pImpTwainInstance->hTwainWnd != pMsg->hwnd ) || !pImpTwainInstance->ImplHandleMsg( (void*) lParam ) )
00210 {
00211 return CallNextHookEx( pImpTwainInstance->hTwainHook, nCode, wParam, lParam );
00212 }
00213 else
00214 {
00215 pMsg->message = WM_USER;
00216 pMsg->lParam = 0;
00217
00218 return 0;
00219 }
00220 }
00221
00222
00223
00224
00225 ImpTwain::ImpTwain( ScannerManager& rMgr, const Link& rNotifyLink ) :
00226 mrMgr( rMgr ),
00227 mxMgr( uno::Reference< scanner::XScannerManager >( static_cast< OWeakObject* >( &rMgr ), uno::UNO_QUERY) ),
00228 aNotifyLink( rNotifyLink ),
00229 pDSM( NULL ),
00230 pMod( NULL ),
00231 hTwainWnd( 0 ),
00232 hTwainHook( 0 ),
00233 nCurState( 1 ),
00234 mbCloseFrameOnExit( false )
00235 {
00236
00237 pImpTwainInstance = this;
00238
00239 aAppIdent.Id = 0;
00240 aAppIdent.Version.MajorNum = 1;
00241 aAppIdent.Version.MinorNum = 0;
00242 aAppIdent.Version.Language = TWLG_USA;
00243 aAppIdent.Version.Country = TWCY_USA;
00244 aAppIdent.ProtocolMajor = TWON_PROTOCOLMAJOR;
00245 aAppIdent.ProtocolMinor = TWON_PROTOCOLMINOR;
00246 aAppIdent.SupportedGroups = DG_IMAGE | DG_CONTROL;
00247 strncpy( aAppIdent.Version.Info, "8.0", 32 );
00248 aAppIdent.Version.Info[32] = aAppIdent.Version.Info[33] = 0;
00249 strncpy( aAppIdent.Manufacturer, "Sun Microsystems", 32 );
00250 aAppIdent.Manufacturer[32] = aAppIdent.Manufacturer[33] = 0;
00251 strncpy( aAppIdent.ProductFamily,"Office", 32 );
00252 aAppIdent.ProductFamily[32] = aAppIdent.ProductFamily[33] = 0;
00253 strncpy( aAppIdent.ProductName, "Office", 32 );
00254 aAppIdent.ProductName[32] = aAppIdent.ProductName[33] = 0;
00255
00256 WNDCLASS aWc = { 0, &TwainWndProc, 0, sizeof( WNDCLASS ), GetModuleHandle( NULL ), NULL, NULL, NULL, NULL, "TwainClass" };
00257 RegisterClass( &aWc );
00258
00259 hTwainWnd = CreateWindowEx( WS_EX_TOPMOST, aWc.lpszClassName, "TWAIN", 0, 0, 0, 0, 0, HWND_DESKTOP, NULL, aWc.hInstance, 0 );
00260 hTwainHook = SetWindowsHookEx( WH_GETMESSAGE, &TwainMsgProc, NULL, GetCurrentThreadId() );
00261
00262
00263 mxSelfRef = static_cast< ::cppu::OWeakObject* >( this );
00264 }
00265
00266
00267
00268 ImpTwain::~ImpTwain()
00269 {
00270
00271 if( mbCloseFrameOnExit )
00272 ImplSendCloseEvent();
00273 }
00274
00275
00276
00277 void ImpTwain::Destroy()
00278 {
00279 ImplFallback( TWAIN_EVENT_NONE );
00280 Application::PostUserEvent( LINK( this, ImpTwain, ImplDestroyHdl ), NULL );
00281 }
00282
00283
00284
00285 bool ImpTwain::SelectSource()
00286 {
00287 TW_UINT16 nRet = TWRC_FAILURE;
00288
00289 ImplOpenSourceManager();
00290
00291 if( 3 == nCurState )
00292 {
00293 TW_IDENTITY aIdent;
00294
00295 aIdent.Id = 0, aIdent.ProductName[ 0 ] = '\0';
00296 aNotifyLink.Call( (void*) TWAIN_EVENT_SCANNING );
00297 nRet = PFUNC( &aAppIdent, NULL, DG_CONTROL, DAT_IDENTITY, MSG_USERSELECT, &aIdent );
00298 }
00299
00300 ImplFallback( TWAIN_EVENT_QUIT );
00301
00302 return( TWRC_SUCCESS == nRet );
00303 }
00304
00305
00306
00307 bool ImpTwain::InitXfer()
00308 {
00309 bool bRet = false;
00310
00311 ImplOpenSourceManager();
00312
00313 if( 3 == nCurState )
00314 {
00315 ImplOpenSource();
00316
00317 if( 4 == nCurState )
00318 bRet = ImplEnableSource();
00319 }
00320
00321 if( !bRet )
00322 ImplFallback( TWAIN_EVENT_QUIT );
00323
00324 return bRet;
00325 }
00326
00327
00328
00329 void ImpTwain::ImplOpenSourceManager()
00330 {
00331 if( 1 == nCurState )
00332 {
00333 pMod = new ::vos::OModule( ::rtl::OUString() );
00334
00335 if( pMod->load( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( TWAIN_LIBNAME ) ) ) )
00336 {
00337 nCurState = 2;
00338
00339 if( ( ( pDSM = (DSMENTRYPROC) pMod->getSymbol( String( RTL_CONSTASCII_USTRINGPARAM( TWAIN_FUNCNAME ) ) ) ) != NULL ) &&
00340 ( PFUNC( &aAppIdent, NULL, DG_CONTROL, DAT_PARENT, MSG_OPENDSM, &hTwainWnd ) == TWRC_SUCCESS ) )
00341 {
00342 nCurState = 3;
00343 }
00344 }
00345 else
00346 {
00347 delete pMod;
00348 pMod = NULL;
00349 }
00350 }
00351 }
00352
00353
00354
00355 void ImpTwain::ImplOpenSource()
00356 {
00357 if( 3 == nCurState )
00358 {
00359 if( ( PFUNC( &aAppIdent, NULL, DG_CONTROL, DAT_IDENTITY, MSG_GETDEFAULT, &aSrcIdent ) == TWRC_SUCCESS ) &&
00360 ( PFUNC( &aAppIdent, NULL, DG_CONTROL, DAT_IDENTITY, MSG_OPENDS, &aSrcIdent ) == TWRC_SUCCESS ) )
00361 {
00362 TW_CAPABILITY aCap = { CAP_XFERCOUNT, TWON_ONEVALUE, GlobalAlloc( GHND, sizeof( TW_ONEVALUE ) ) };
00363 TW_ONEVALUE* pVal = (TW_ONEVALUE*) GlobalLock( aCap.hContainer );
00364
00365 pVal->ItemType = TWTY_INT16, pVal->Item = 1;
00366 GlobalUnlock( aCap.hContainer );
00367 PFUNC( &aAppIdent, &aSrcIdent, DG_CONTROL, DAT_CAPABILITY, MSG_SET, &aCap );
00368 GlobalFree( aCap.hContainer );
00369 nCurState = 4;
00370 }
00371 }
00372 }
00373
00374
00375
00376 bool ImpTwain::ImplEnableSource()
00377 {
00378 bool bRet = false;
00379
00380 if( 4 == nCurState )
00381 {
00382 TW_USERINTERFACE aUI = { true, true, hTwainWnd };
00383
00384 aNotifyLink.Call( (void*) TWAIN_EVENT_SCANNING );
00385 nCurState = 5;
00386
00387
00388 ImplRegisterCloseListener();
00389
00390 if( PFUNC( &aAppIdent, &aSrcIdent, DG_CONTROL, DAT_USERINTERFACE, MSG_ENABLEDS, &aUI ) == TWRC_SUCCESS )
00391 {
00392 bRet = true;
00393 }
00394 else
00395 {
00396 nCurState = 4;
00397
00398
00399 ImplDeregisterCloseListener();
00400 }
00401 }
00402
00403 return bRet;
00404 }
00405
00406
00407
00408 bool ImpTwain::ImplHandleMsg( void* pMsg )
00409 {
00410 TW_UINT16 nRet;
00411 PTWAINMSG pMess = (PTWAINMSG) pMsg;
00412 TW_EVENT aEvt = { pMess, MSG_NULL };
00413
00414 nRet = PFUNC( &aAppIdent, &aSrcIdent, DG_CONTROL, DAT_EVENT, MSG_PROCESSEVENT, &aEvt );
00415
00416 if( aEvt.TWMessage != MSG_NULL )
00417 {
00418 switch( aEvt.TWMessage )
00419 {
00420 case MSG_XFERREADY:
00421 {
00422 ULONG nEvent = TWAIN_EVENT_QUIT;
00423
00424 if( 5 == nCurState )
00425 {
00426 nCurState = 6;
00427 ImplXfer();
00428
00429 if( mrMgr.GetData() )
00430 nEvent = TWAIN_EVENT_XFER;
00431 }
00432
00433 ImplFallback( nEvent );
00434 }
00435 break;
00436
00437 case MSG_CLOSEDSREQ:
00438 ImplFallback( TWAIN_EVENT_QUIT );
00439 break;
00440
00441 default:
00442 break;
00443 }
00444 }
00445 else
00446 nRet = TWRC_NOTDSEVENT;
00447
00448 return( TWRC_DSEVENT == nRet );
00449 }
00450
00451
00452
00453 void ImpTwain::ImplXfer()
00454 {
00455 if( nCurState == 6 )
00456 {
00457 TW_IMAGEINFO aInfo;
00458 TW_UINT32 hDIB = 0;
00459 long nWidth, nHeight, nXRes, nYRes;
00460
00461 if( PFUNC( &aAppIdent, &aSrcIdent, DG_IMAGE, DAT_IMAGEINFO, MSG_GET, &aInfo ) == TWRC_SUCCESS )
00462 {
00463 nWidth = aInfo.ImageWidth;
00464 nHeight = aInfo.ImageLength;
00465 nXRes = FIXTOLONG( aInfo.XResolution );
00466 nYRes = FIXTOLONG( aInfo.YResolution );
00467 }
00468 else
00469 nWidth = nHeight = nXRes = nYRes = -1L;
00470
00471 switch( PFUNC( &aAppIdent, &aSrcIdent, DG_IMAGE, DAT_IMAGENATIVEXFER, MSG_GET, &hDIB ) )
00472 {
00473 case( TWRC_CANCEL ):
00474 nCurState = 7;
00475 break;
00476
00477 case( TWRC_XFERDONE ):
00478 {
00479 if( hDIB )
00480 {
00481 if( ( nXRes != -1 ) && ( nYRes != - 1 ) && ( nWidth != - 1 ) && ( nHeight != - 1 ) )
00482 {
00483
00484 BITMAPINFOHEADER* pBIH = (BITMAPINFOHEADER*) GlobalLock( (HGLOBAL) hDIB );
00485 static const double fFactor = 100.0 / 2.54;
00486
00487 pBIH->biXPelsPerMeter = FRound( fFactor * nXRes );
00488 pBIH->biYPelsPerMeter = FRound( fFactor * nYRes );
00489
00490 GlobalUnlock( (HGLOBAL) hDIB );
00491 }
00492
00493 mrMgr.SetData( (void*)(long) hDIB );
00494 }
00495 else
00496 GlobalFree( (HGLOBAL) hDIB );
00497
00498 nCurState = 7;
00499 }
00500 break;
00501
00502 default:
00503 break;
00504 }
00505 }
00506 }
00507
00508
00509
00510 void ImpTwain::ImplFallback( ULONG nEvent )
00511 {
00512 Application::PostUserEvent( LINK( this, ImpTwain, ImplFallbackHdl ), (void*) nEvent );
00513 }
00514
00515
00516
00517 IMPL_LINK( ImpTwain, ImplFallbackHdl, void*, pData )
00518 {
00519 const ULONG nEvent = (ULONG) pData;
00520 bool bFallback = true;
00521
00522 switch( nCurState )
00523 {
00524 case( 7 ):
00525 case( 6 ):
00526 {
00527 TW_PENDINGXFERS aXfers;
00528
00529 if( PFUNC( &aAppIdent, &aSrcIdent, DG_CONTROL, DAT_PENDINGXFERS, MSG_ENDXFER, &aXfers ) == TWRC_SUCCESS )
00530 {
00531 if( aXfers.Count != 0 )
00532 PFUNC( &aAppIdent, &aSrcIdent, DG_CONTROL, DAT_PENDINGXFERS, MSG_RESET, &aXfers );
00533 }
00534
00535 nCurState = 5;
00536 }
00537 break;
00538
00539 case( 5 ):
00540 {
00541 TW_USERINTERFACE aUI = { true, true, hTwainWnd };
00542
00543 PFUNC( &aAppIdent, &aSrcIdent, DG_CONTROL, DAT_USERINTERFACE, MSG_DISABLEDS, &aUI );
00544 nCurState = 4;
00545
00546
00547 ImplDeregisterCloseListener();
00548 }
00549 break;
00550
00551 case( 4 ):
00552 {
00553 PFUNC( &aAppIdent, NULL, DG_CONTROL, DAT_IDENTITY, MSG_CLOSEDS, &aSrcIdent );
00554 nCurState = 3;
00555 }
00556 break;
00557
00558 case( 3 ):
00559 {
00560 PFUNC( &aAppIdent, NULL, DG_CONTROL, DAT_PARENT, MSG_CLOSEDSM, &hTwainWnd );
00561 nCurState = 2;
00562 }
00563 break;
00564
00565 case( 2 ):
00566 {
00567 delete pMod;
00568 pMod = NULL;
00569 nCurState = 1;
00570 }
00571 break;
00572
00573 default:
00574 {
00575 if( nEvent != TWAIN_EVENT_NONE )
00576 aNotifyLink.Call( (void*) nEvent );
00577
00578 bFallback = false;
00579 }
00580 break;
00581 }
00582
00583 if( bFallback )
00584 ImplFallback( nEvent );
00585
00586 return 0L;
00587 }
00588
00589
00590
00591 IMPL_LINK( ImpTwain, ImplDestroyHdl, void*, )
00592 {
00593 if( hTwainWnd )
00594 DestroyWindow( hTwainWnd );
00595
00596 if( hTwainHook )
00597 UnhookWindowsHookEx( hTwainHook );
00598
00599
00600
00601 mxSelfRef = NULL;
00602 pImpTwainInstance = NULL;
00603
00604 return 0L;
00605 }
00606
00607
00608
00609 uno::Reference< frame::XFrame > ImpTwain::ImplGetActiveFrame()
00610 {
00611 try
00612 {
00613 uno::Reference< lang::XMultiServiceFactory > xMgr( ::comphelper::getProcessServiceFactory() );
00614
00615 if( xMgr.is() )
00616 {
00617
00618 uno::Reference< frame::XDesktop > xDesktop( xMgr->createInstance(
00619 OUString::createFromAscii( "com.sun.star.frame.Desktop" ) ), uno::UNO_QUERY );
00620
00621 if( xDesktop.is() )
00622 {
00623
00624 uno::Reference< beans::XPropertySet > xDesktopProps( xDesktop, uno::UNO_QUERY );
00625
00626 if( xDesktopProps.is() )
00627 {
00628 uno::Any aActiveFrame;
00629
00630 try
00631 {
00632 aActiveFrame = xDesktopProps->getPropertyValue(
00633 OUString::createFromAscii( "ActiveFrame" ) );
00634 }
00635 catch( const beans::UnknownPropertyException& )
00636 {
00637
00638 DBG_ERROR("ImpTwain::ImplGetActiveFrame: ActiveFrame property unknown, cannot determine active frame!");
00639 return uno::Reference< frame::XFrame >();
00640 }
00641
00642 uno::Reference< frame::XFrame > xActiveFrame;
00643
00644 if( (aActiveFrame >>= xActiveFrame) &&
00645 xActiveFrame.is() )
00646 {
00647 return xActiveFrame;
00648 }
00649 }
00650 }
00651 }
00652 }
00653 catch( const uno::Exception& )
00654 {
00655 }
00656
00657 DBG_ERROR("ImpTwain::ImplGetActiveFrame: Could not determine active frame!");
00658 return uno::Reference< frame::XFrame >();
00659 }
00660
00661
00662
00663 uno::Reference< util::XCloseBroadcaster > ImpTwain::ImplGetActiveFrameCloseBroadcaster()
00664 {
00665 try
00666 {
00667 return uno::Reference< util::XCloseBroadcaster >( ImplGetActiveFrame(), uno::UNO_QUERY );
00668 }
00669 catch( const uno::Exception& )
00670 {
00671 }
00672
00673 DBG_ERROR("ImpTwain::ImplGetActiveFrameCloseBroadcaster: Could determine close broadcaster on active frame!");
00674 return uno::Reference< util::XCloseBroadcaster >();
00675 }
00676
00677
00678
00679 void ImpTwain::ImplRegisterCloseListener()
00680 {
00681 try
00682 {
00683 uno::Reference< util::XCloseBroadcaster > xCloseBroadcaster( ImplGetActiveFrameCloseBroadcaster() );
00684
00685 if( xCloseBroadcaster.is() )
00686 {
00687 xCloseBroadcaster->addCloseListener(this);
00688 return;
00689 }
00690 else
00691 {
00692
00693 DBG_ERROR("ImpTwain::ImplRegisterCloseListener: XFrame has no XCloseBroadcaster!");
00694 return;
00695 }
00696 }
00697 catch( const uno::Exception& )
00698 {
00699 }
00700
00701 DBG_ERROR("ImpTwain::ImplRegisterCloseListener: Could not register as close listener!");
00702 }
00703
00704
00705
00706 void ImpTwain::ImplDeregisterCloseListener()
00707 {
00708 try
00709 {
00710 uno::Reference< util::XCloseBroadcaster > xCloseBroadcaster(
00711 ImplGetActiveFrameCloseBroadcaster() );
00712
00713 if( xCloseBroadcaster.is() )
00714 {
00715 xCloseBroadcaster->removeCloseListener(this);
00716 return;
00717 }
00718 else
00719 {
00720
00721 DBG_ERROR("ImpTwain::ImplDeregisterCloseListener: XFrame has no XCloseBroadcaster!");
00722 return;
00723 }
00724 }
00725 catch( const uno::Exception& )
00726 {
00727 }
00728
00729 DBG_ERROR("ImpTwain::ImplDeregisterCloseListener: Could not deregister as close listener!");
00730 }
00731
00732
00733
00734 void SAL_CALL ImpTwain::queryClosing( const lang::EventObject& , sal_Bool GetsOwnership ) throw (util::CloseVetoException, uno::RuntimeException)
00735 {
00736
00737 mbCloseFrameOnExit = GetsOwnership;
00738
00739
00740 throw util::CloseVetoException();
00741 }
00742
00743
00744
00745 void SAL_CALL ImpTwain::notifyClosing( const lang::EventObject& ) throw (uno::RuntimeException)
00746 {
00747
00748 DBG_ERROR("ImpTwain::notifyClosing called, but we vetoed the closing before!");
00749 }
00750
00751
00752
00753 void SAL_CALL ImpTwain::disposing( const lang::EventObject& ) throw (uno::RuntimeException)
00754 {
00755
00756 }
00757
00758
00759
00760 void ImpTwain::ImplSendCloseEvent()
00761 {
00762 try
00763 {
00764 uno::Reference< util::XCloseable > xCloseable( ImplGetActiveFrame(), uno::UNO_QUERY );
00765
00766 if( xCloseable.is() )
00767 xCloseable->close( true );
00768 }
00769 catch( const uno::Exception& )
00770 {
00771 }
00772
00773 DBG_ERROR("ImpTwain::ImplSendCloseEvent: Could not send required close broadcast!");
00774 }
00775
00776
00777
00778
00779
00780
00781 class Twain
00782 {
00783 uno::Reference< lang::XEventListener > mxListener;
00784 uno::Reference< scanner::XScannerManager > mxMgr;
00785 const ScannerManager* mpCurMgr;
00786 ImpTwain* mpImpTwain;
00787 TwainState meState;
00788
00789 DECL_LINK( ImpNotifyHdl, ImpTwain* );
00790
00791 public:
00792
00793 Twain();
00794 ~Twain();
00795
00796 bool SelectSource( ScannerManager& rMgr );
00797 bool PerformTransfer( ScannerManager& rMgr, const uno::Reference< lang::XEventListener >& rxListener );
00798
00799 TwainState GetState() const { return meState; }
00800 };
00801
00802
00803
00804 Twain::Twain() :
00805 mpCurMgr( NULL ),
00806 mpImpTwain( NULL ),
00807 meState( TWAIN_STATE_NONE )
00808 {
00809 }
00810
00811
00812
00813 Twain::~Twain()
00814 {
00815 if( mpImpTwain )
00816 mpImpTwain->Destroy();
00817 }
00818
00819
00820
00821 bool Twain::SelectSource( ScannerManager& rMgr )
00822 {
00823 bool bRet;
00824
00825 if( !mpImpTwain )
00826 {
00827
00828 mxMgr = uno::Reference< scanner::XScannerManager >( static_cast< OWeakObject* >( const_cast< ScannerManager* >( mpCurMgr = &rMgr ) ),
00829 uno::UNO_QUERY ),
00830
00831 meState = TWAIN_STATE_NONE;
00832 mpImpTwain = new ImpTwain( rMgr, LINK( this, Twain, ImpNotifyHdl ) );
00833 bRet = mpImpTwain->SelectSource();
00834 }
00835 else
00836 bRet = false;
00837
00838 return bRet;
00839 }
00840
00841
00842
00843 bool Twain::PerformTransfer( ScannerManager& rMgr, const uno::Reference< lang::XEventListener >& rxListener )
00844 {
00845 bool bRet;
00846
00847 if( !mpImpTwain )
00848 {
00849
00850 mxMgr = uno::Reference< scanner::XScannerManager >( static_cast< OWeakObject* >( const_cast< ScannerManager* >( mpCurMgr = &rMgr ) ),
00851 uno::UNO_QUERY ),
00852
00853 mxListener = rxListener;
00854 meState = TWAIN_STATE_NONE;
00855 mpImpTwain = new ImpTwain( rMgr, LINK( this, Twain, ImpNotifyHdl ) );
00856 bRet = mpImpTwain->InitXfer();
00857 }
00858 else
00859 bRet = false;
00860
00861 return bRet;
00862 }
00863
00864
00865
00866 IMPL_LINK( Twain, ImpNotifyHdl, ImpTwain*, nEvent )
00867 {
00868 switch( (ULONG)(void*) nEvent )
00869 {
00870 case( TWAIN_EVENT_SCANNING ):
00871 meState = TWAIN_STATE_SCANNING;
00872 break;
00873
00874 case( TWAIN_EVENT_QUIT ):
00875 {
00876 if( meState != TWAIN_STATE_DONE )
00877 meState = TWAIN_STATE_CANCELED;
00878
00879 if( mpImpTwain )
00880 {
00881 mpImpTwain->Destroy();
00882 mpImpTwain = NULL;
00883 mpCurMgr = NULL;
00884 }
00885
00886 if( mxListener.is() )
00887 mxListener->disposing( lang::EventObject( mxMgr ) );
00888
00889 mxListener = NULL;
00890 }
00891 break;
00892
00893 case( TWAIN_EVENT_XFER ):
00894 {
00895 if( mpImpTwain )
00896 {
00897 meState = ( mpCurMgr->GetData() ? TWAIN_STATE_DONE : TWAIN_STATE_CANCELED );
00898
00899 mpImpTwain->Destroy();
00900 mpImpTwain = NULL;
00901 mpCurMgr = NULL;
00902
00903 if( mxListener.is() )
00904 mxListener->disposing( lang::EventObject( mxMgr ) );
00905 }
00906
00907 mxListener = NULL;
00908 }
00909 break;
00910
00911 default:
00912 break;
00913 }
00914
00915 return 0L;
00916 }
00917
00918
00919
00920
00921
00922 static Twain aTwain;
00923
00924
00925
00926
00927
00928 void ScannerManager::DestroyData()
00929 {
00930 if( mpData )
00931 {
00932 GlobalFree( (HGLOBAL)(long) mpData );
00933 mpData = NULL;
00934 }
00935 }
00936
00937
00938
00939 AWT::Size ScannerManager::getSize() throw()
00940 {
00941 AWT::Size aRet;
00942 HGLOBAL hDIB = (HGLOBAL)(long) mpData;
00943
00944 if( hDIB )
00945 {
00946 BITMAPINFOHEADER* pBIH = (BITMAPINFOHEADER*) GlobalLock( hDIB );
00947
00948 if( pBIH )
00949 {
00950 aRet.Width = pBIH->biWidth;
00951 aRet.Height = pBIH->biHeight;
00952 }
00953 else
00954 aRet.Width = aRet.Height = 0;
00955
00956 GlobalUnlock( hDIB );
00957 }
00958 else
00959 aRet.Width = aRet.Height = 0;
00960
00961 return aRet;
00962 }
00963
00964
00965
00966 SEQ( sal_Int8 ) ScannerManager::getDIB() throw()
00967 {
00968 SEQ( sal_Int8 ) aRet;
00969
00970 if( mpData )
00971 {
00972 HGLOBAL hDIB = (HGLOBAL)(long) mpData;
00973 const sal_uInt32 nDIBSize = GlobalSize( hDIB );
00974 BITMAPINFOHEADER* pBIH = (BITMAPINFOHEADER*) GlobalLock( hDIB );
00975
00976 if( pBIH )
00977 {
00978 sal_uInt32 nColEntries;
00979
00980 switch( pBIH->biBitCount )
00981 {
00982 case( 1 ):
00983 case( 4 ):
00984 case( 8 ):
00985 nColEntries = pBIH->biClrUsed ? pBIH->biClrUsed : ( 1 << pBIH->biBitCount );
00986 break;
00987
00988 case( 24 ):
00989 nColEntries = pBIH->biClrUsed ? pBIH->biClrUsed : 0;
00990 break;
00991
00992 case( 16 ):
00993 case( 32 ):
00994 {
00995 nColEntries = pBIH->biClrUsed;
00996
00997 if( pBIH->biCompression == BI_BITFIELDS )
00998 nColEntries += 3;
00999 }
01000 break;
01001
01002 default:
01003 nColEntries = 0;
01004 break;
01005 }
01006
01007 aRet = SEQ( sal_Int8 )( sizeof( BITMAPFILEHEADER ) + nDIBSize );
01008
01009 sal_Int8* pBuf = aRet.getArray();
01010 SvMemoryStream* pMemStm = new SvMemoryStream( (char*) pBuf, sizeof( BITMAPFILEHEADER ), STREAM_WRITE );
01011
01012 *pMemStm << 'B' << 'M' << (sal_uInt32) 0 << (sal_uInt32) 0;
01013 *pMemStm << (sal_uInt32) ( sizeof( BITMAPFILEHEADER ) + pBIH->biSize + ( nColEntries * sizeof( RGBQUAD ) ) );
01014
01015 delete pMemStm;
01016 memcpy( pBuf + sizeof( BITMAPFILEHEADER ), pBIH, nDIBSize );
01017 }
01018
01019 GlobalUnlock( hDIB );
01020 DestroyData();
01021 }
01022
01023 return aRet;
01024 }
01025
01026
01027
01028 SEQ( ScannerContext ) SAL_CALL ScannerManager::getAvailableScanners() throw()
01029 {
01030 vos::OGuard aGuard( maProtector );
01031 SEQ( ScannerContext ) aRet( 1 );
01032
01033 aRet.getArray()[0].ScannerName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "TWAIN" ) );
01034 aRet.getArray()[0].InternalData = 0;
01035
01036 return aRet;
01037 }
01038
01039
01040
01041 BOOL SAL_CALL ScannerManager::configureScanner( ScannerContext& rContext )
01042 throw( ScannerException )
01043 {
01044 vos::OGuard aGuard( maProtector );
01045 uno::Reference< XScannerManager > xThis( this );
01046
01047 if( rContext.InternalData != 0 || rContext.ScannerName != ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "TWAIN" ) ) )
01048 throw ScannerException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Scanner does not exist" ) ), xThis, ScanError_InvalidContext );
01049
01050 DestroyData();
01051
01052 return aTwain.SelectSource( *this );
01053 }
01054
01055
01056
01057 void SAL_CALL ScannerManager::startScan( const ScannerContext& rContext, const uno::Reference< lang::XEventListener >& rxListener )
01058 throw( ScannerException )
01059 {
01060 vos::OGuard aGuard( maProtector );
01061 uno::Reference< XScannerManager > xThis( this );
01062
01063 if( rContext.InternalData != 0 || rContext.ScannerName != ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "TWAIN" ) ) )
01064 throw ScannerException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Scanner does not exist" ) ), xThis, ScanError_InvalidContext );
01065
01066 DestroyData();
01067 aTwain.PerformTransfer( *this, rxListener );
01068 }
01069
01070
01071
01072 ScanError SAL_CALL ScannerManager::getError( const ScannerContext& rContext )
01073 throw( ScannerException )
01074 {
01075 vos::OGuard aGuard( maProtector );
01076 uno::Reference< XScannerManager > xThis( this );
01077
01078 if( rContext.InternalData != 0 || rContext.ScannerName != ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "TWAIN" ) ) )
01079 throw ScannerException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Scanner does not exist" ) ), xThis, ScanError_InvalidContext );
01080
01081 return( ( aTwain.GetState() == TWAIN_STATE_CANCELED ) ? ScanError_ScanCanceled : ScanError_ScanErrorNone );
01082 }
01083
01084
01085
01086 uno::Reference< awt::XBitmap > SAL_CALL ScannerManager::getBitmap( const ScannerContext& )
01087 throw( ScannerException )
01088 {
01089 vos::OGuard aGuard( maProtector );
01090 return uno::Reference< awt::XBitmap >( this );
01091 }