Files
libreoffice/extensions/source/scanner/scanwin.cxx

1098 lines
33 KiB
C++
Raw Normal View History

2000-09-18 15:18:56 +00:00
/*************************************************************************
*
* OpenOffice.org - a multi-platform office productivity suite
2000-09-18 15:18:56 +00:00
*
* $RCSfile: scanwin.cxx,v $
2000-09-18 15:18:56 +00:00
*
* $Revision: 1.7 $
2000-09-18 15:18:56 +00:00
*
* last change: $Author: rt $ $Date: 2005-09-08 20:39:15 $
2000-09-18 15:18:56 +00:00
*
* The Contents of this file are made available subject to
* the terms of GNU Lesser General Public License Version 2.1.
2000-09-18 15:18:56 +00:00
*
*
* GNU Lesser General Public License Version 2.1
* =============================================
* Copyright 2005 by Sun Microsystems, Inc.
* 901 San Antonio Road, Palo Alto, CA 94303, USA
2000-09-18 15:18:56 +00:00
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License version 2.1, as published by the Free Software Foundation.
2000-09-18 15:18:56 +00:00
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
2000-09-18 15:18:56 +00:00
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
2000-09-18 15:18:56 +00:00
*
************************************************************************/
#ifndef _COM_SUN_STAR_UNO_ANY_HXX_
#include <com/sun/star/uno/Any.hxx>
#endif
#ifndef _COM_SUN_STAR_UNO_REFERENCE_HXX_
#include <com/sun/star/uno/Reference.hxx>
#endif
#ifndef _COM_SUN_STAR_UTIL_XCLOSEABLE_HPP_
#include <com/sun/star/util/XCloseable.hpp>
#endif
#ifndef _COM_SUN_STAR_UTIL_XCLOSEBROADCASTER_HPP_
#include <com/sun/star/util/XCloseBroadcaster.hpp>
#endif
#ifndef _COM_SUN_STAR_UTIL_XCLOSELISTENER_HPP_
#include <com/sun/star/util/XCloseListener.hpp>
#endif
#ifndef _COM_SUN_STAR_FRAME_XFRAME_HPP_
#include <com/sun/star/frame/XFrame.hpp>
#endif
#ifndef _COM_SUN_STAR_FRAME_XDESKTOP_HPP_
#include <com/sun/star/frame/XDesktop.hpp>
#endif
#ifndef _COM_SUN_STAR_BEANS_XPROPERTYSET_HPP_
#include <com/sun/star/beans/XPropertySet.hpp>
#endif
#ifndef _CPPUHELPER_IMPLBASE1_HXX_
#include <cppuhelper/implbase1.hxx>
#endif
#ifndef _COMPHELPER_PROCESSFACTORY_HXX_
#include <comphelper/processfactory.hxx>
#endif
2000-09-18 15:18:56 +00:00
#include <math.h>
#include <tools/svwin.h>
#include <tools/stream.hxx>
#include <vos/mutex.hxx>
#include <vos/module.hxx>
#include <vcl/svapp.hxx>
#include <vcl/wrkwin.hxx>
#include <vcl/sysdata.hxx>
#include <vcl/salbtype.hxx>
#include "scanner.hxx"
#include "twain/twain.h"
using namespace ::com::sun::star;
2000-09-18 15:18:56 +00:00
// -----------
// - Defines -
// -----------
#define TWAIN_SELECT 0x00000001UL
#define TWAIN_ACQUIRE 0x00000002UL
#define TWAIN_TERMINATE 0xFFFFFFFFUL
#define TWAIN_EVENT_NONE 0x00000000UL
#define TWAIN_EVENT_QUIT 0x00000001UL
#define TWAIN_EVENT_SCANNING 0x00000002UL
#define TWAIN_EVENT_XFER 0x00000004UL
#define PFUNC (*pDSM)
#define PTWAINMSG MSG*
#define FIXTODOUBLE( nFix ) ((double)nFix.Whole+(double)nFix.Frac/65536.)
#define FIXTOLONG( nFix ) ((long)floor(FIXTODOUBLE(nFix)+0.5))
#if defined WIN
#define TWAIN_LIBNAME "TWAIN.DLL"
#define TWAIN_FUNCNAME "DSM_Entry"
#elif defined WNT
#define TWAIN_LIBNAME "TWAIN_32.DLL"
#define TWAIN_FUNCNAME "DSM_Entry"
#endif
// --------------
// - TwainState -
// --------------
enum TwainState
{
TWAIN_STATE_NONE = 0,
TWAIN_STATE_SCANNING = 1,
TWAIN_STATE_DONE = 2,
TWAIN_STATE_CANCELED = 3
};
// ------------
// - ImpTwain -
// ------------
typedef ::cppu::WeakImplHelper1< ::com::sun::star::util::XCloseListener > CloseListenerBase;
2000-09-18 15:18:56 +00:00
class ImpTwain : public CloseListenerBase
{
REF( com::sun::star::scanner::XScannerManager ) mxMgr;
ScannerManager* mpMgr;
TW_IDENTITY aAppIdent;
TW_IDENTITY aSrcIdent;
Link aNotifyLink;
DSMENTRYPROC pDSM;
NAMESPACE_VOS( OModule )* pMod;
ULONG nCurState;
bool mbCloseFrameOnExit;
uno::Reference< uno::XInterface > mxSelfRef;
void ImplCreate();
void ImplOpenSourceManager();
void ImplOpenSource();
BOOL ImplEnableSource();
void ImplXfer();
void ImplFallback( ULONG nEvent );
void ImplSendCloseEvent();
void ImplDeregisterCloseListener();
void ImplRegisterCloseListener();
uno::Reference< frame::XFrame > ImplGetActiveFrame();
uno::Reference< util::XCloseBroadcaster > ImplGetActiveFrameCloseBroadcaster();
DECL_LINK( ImplFallbackHdl, void* );
DECL_LINK( ImplDestroyHdl, void* );
2000-09-18 15:18:56 +00:00
public:
HWND hTwainWnd;
HHOOK hTwainHook;
BOOL ImplHandleMsg( void* pMsg );
public:
ImpTwain( ScannerManager* pMgr, const Link& rNotifyLink );
~ImpTwain();
void Destroy();
BOOL SelectSource();
BOOL InitXfer();
// from util::XCloseListener
virtual void SAL_CALL queryClosing( const ::com::sun::star::lang::EventObject& Source, sal_Bool GetsOwnership ) throw (::com::sun::star::util::CloseVetoException, ::com::sun::star::uno::RuntimeException);
virtual void SAL_CALL notifyClosing( const ::com::sun::star::lang::EventObject& Source ) throw (::com::sun::star::uno::RuntimeException);
// from lang::XEventListener
virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& Source ) throw (::com::sun::star::uno::RuntimeException);
2000-09-18 15:18:56 +00:00
};
// ---------
// - Procs -
// ---------
static ImpTwain* pImpTwainInstance = NULL;
// -------------------------------------------------------------------------
LRESULT CALLBACK TwainWndProc( HWND hWnd,UINT nMsg, WPARAM nPar1, LPARAM nPar2 )
{
return DefWindowProc( hWnd, nMsg, nPar1, nPar2 );
}
// -------------------------------------------------------------------------
LRESULT CALLBACK TwainMsgProc( int nCode, WPARAM wParam, LPARAM lParam )
{
MSG* pMsg = (MSG*) lParam;
if( ( nCode < 0 ) ||
( pImpTwainInstance->hTwainWnd != pMsg->hwnd ) ||
!pImpTwainInstance->ImplHandleMsg( (void*) lParam ) )
{
return CallNextHookEx( pImpTwainInstance->hTwainHook, nCode, wParam, lParam );
}
else
{
pMsg->message = WM_USER;
pMsg->lParam = 0;
return 0;
}
}
// -----------------------------------------------------------------------------
ImpTwain::ImpTwain( ScannerManager* pMgr, const Link& rNotifyLink ) :
// #107835# hold reference to ScannerManager, to prevent premature death
mxMgr ( REF(com::sun::star::scanner::XScannerManager)(
static_cast< OWeakObject* >(pMgr),
::com::sun::star::uno::UNO_QUERY) ),
mpMgr ( pMgr ),
aNotifyLink ( rNotifyLink ),
pDSM ( NULL ),
pMod ( NULL ),
hTwainWnd ( 0 ),
hTwainHook ( 0 ),
nCurState ( 1 ),
mbCloseFrameOnExit ( false )
2000-09-18 15:18:56 +00:00
{
// setup TWAIN window
2000-09-18 15:18:56 +00:00
pImpTwainInstance = this;
aAppIdent.Id = 0;
aAppIdent.Version.MajorNum = 1;
aAppIdent.Version.MinorNum = 0;
aAppIdent.Version.Language = TWLG_USA;
aAppIdent.Version.Country = TWCY_USA;
aAppIdent.ProtocolMajor = TWON_PROTOCOLMAJOR;
aAppIdent.ProtocolMinor = TWON_PROTOCOLMINOR;
aAppIdent.SupportedGroups = DG_IMAGE | DG_CONTROL;
strncpy( aAppIdent.Version.Info, "6.1", 32 );
aAppIdent.Version.Info[32] = aAppIdent.Version.Info[33] = 0;
strncpy( aAppIdent.Manufacturer, "Sun Microsystems", 32 );
aAppIdent.Manufacturer[32] = aAppIdent.Manufacturer[33] = 0;
strncpy( aAppIdent.ProductFamily,"Office", 32 );
aAppIdent.ProductFamily[32] = aAppIdent.ProductFamily[33] = 0;
strncpy( aAppIdent.ProductName, "Office", 32 );
aAppIdent.ProductName[32] = aAppIdent.ProductName[33] = 0;
2000-09-18 15:18:56 +00:00
HWND hParentWnd = HWND_DESKTOP;
2000-09-18 15:18:56 +00:00
WNDCLASS aWc = { 0, &TwainWndProc, 0, sizeof( WNDCLASS ), GetModuleHandle( NULL ),
NULL, NULL, NULL, NULL, "TwainClass" };
RegisterClass( &aWc );
hTwainWnd = CreateWindowEx( WS_EX_TOPMOST, aWc.lpszClassName, "TWAIN", 0, 0, 0, 0, 0, hParentWnd, NULL, aWc.hInstance, 0 );
hTwainHook = SetWindowsHookEx( WH_GETMESSAGE, &TwainMsgProc, NULL, GetCurrentThreadId() );
// #107835# block destruction until ImplDestroyHdl is called
mxSelfRef = static_cast< ::cppu::OWeakObject* >(this);
2000-09-18 15:18:56 +00:00
}
// -----------------------------------------------------------------------------
ImpTwain::~ImpTwain()
{
// are we responsible for application shutdown?
if( mbCloseFrameOnExit )
ImplSendCloseEvent();
2000-09-18 15:18:56 +00:00
}
// -----------------------------------------------------------------------------
void ImpTwain::Destroy()
{
ImplFallback( TWAIN_EVENT_NONE );
Application::PostUserEvent( LINK( this, ImpTwain, ImplDestroyHdl ), NULL );
}
// -----------------------------------------------------------------------------
BOOL ImpTwain::SelectSource()
{
TW_UINT16 nRet = TWRC_FAILURE;
ImplOpenSourceManager();
if( 3 == nCurState )
{
TW_IDENTITY aIdent;
aIdent.Id = 0, aIdent.ProductName[ 0 ] = '\0';
aNotifyLink.Call( (void*) TWAIN_EVENT_SCANNING );
nRet = PFUNC( &aAppIdent, NULL, DG_CONTROL, DAT_IDENTITY, MSG_USERSELECT, &aIdent );
}
ImplFallback( TWAIN_EVENT_QUIT );
return( TWRC_SUCCESS == nRet );
2000-09-18 15:18:56 +00:00
}
// -----------------------------------------------------------------------------
BOOL ImpTwain::InitXfer()
{
BOOL bRet = FALSE;
ImplOpenSourceManager();
if( 3 == nCurState )
{
ImplOpenSource();
if( 4 == nCurState )
bRet = ImplEnableSource();
}
if( !bRet )
ImplFallback( TWAIN_EVENT_QUIT );
return bRet;
}
// -----------------------------------------------------------------------------
void ImpTwain::ImplOpenSourceManager()
{
if( 1 == nCurState )
{
pMod = new ::vos::OModule( ::rtl::OUString() );
if( pMod->load( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( TWAIN_LIBNAME ) ) ) )
{
nCurState = 2;
if( ( ( pDSM = (DSMENTRYPROC) pMod->getSymbol( String( RTL_CONSTASCII_USTRINGPARAM( TWAIN_FUNCNAME ) ) ) ) != NULL ) &&
( PFUNC( &aAppIdent, NULL, DG_CONTROL, DAT_PARENT, MSG_OPENDSM, &hTwainWnd ) == TWRC_SUCCESS ) )
{
nCurState = 3;
}
}
else
{
delete pMod;
pMod = NULL;
}
}
}
// -----------------------------------------------------------------------------
void ImpTwain::ImplOpenSource()
{
if( 3 == nCurState )
{
if( ( PFUNC( &aAppIdent, NULL, DG_CONTROL, DAT_IDENTITY, MSG_GETDEFAULT, &aSrcIdent ) == TWRC_SUCCESS ) &&
( PFUNC( &aAppIdent, NULL, DG_CONTROL, DAT_IDENTITY, MSG_OPENDS, &aSrcIdent ) == TWRC_SUCCESS ) )
{
TW_CAPABILITY aCap = { CAP_XFERCOUNT, TWON_ONEVALUE, GlobalAlloc( GHND, sizeof( TW_ONEVALUE ) ) };
TW_ONEVALUE* pVal = (TW_ONEVALUE*) GlobalLock( aCap.hContainer );
pVal->ItemType = TWTY_INT16, pVal->Item = 1;
GlobalUnlock( aCap.hContainer );
PFUNC( &aAppIdent, &aSrcIdent, DG_CONTROL, DAT_CAPABILITY, MSG_SET, &aCap );
GlobalFree( aCap.hContainer );
nCurState = 4;
}
}
}
// -----------------------------------------------------------------------------
BOOL ImpTwain::ImplEnableSource()
{
BOOL bRet = FALSE;
if( 4 == nCurState )
{
TW_USERINTERFACE aUI = { TRUE, TRUE, hTwainWnd };
aNotifyLink.Call( (void*) TWAIN_EVENT_SCANNING );
nCurState = 5;
// #107835# register as vetoable close listener, to prevent
// application to die under us
ImplRegisterCloseListener();
2000-09-18 15:18:56 +00:00
if( PFUNC( &aAppIdent, &aSrcIdent, DG_CONTROL, DAT_USERINTERFACE, MSG_ENABLEDS, &aUI ) == TWRC_SUCCESS )
{
2000-09-18 15:18:56 +00:00
bRet = TRUE;
}
2000-09-18 15:18:56 +00:00
else
{
2000-09-18 15:18:56 +00:00
nCurState = 4;
// #107835# deregister as vetoable close listener, dialog failed
ImplDeregisterCloseListener();
}
2000-09-18 15:18:56 +00:00
}
return bRet;
}
// -----------------------------------------------------------------------------
BOOL ImpTwain::ImplHandleMsg( void* pMsg )
{
TW_UINT16 nRet;
PTWAINMSG pMess = (PTWAINMSG) pMsg;
TW_EVENT aEvt = { pMess, MSG_NULL };
nRet = PFUNC( &aAppIdent, &aSrcIdent, DG_CONTROL, DAT_EVENT, MSG_PROCESSEVENT, &aEvt );
if( aEvt.TWMessage != MSG_NULL )
{
switch( aEvt.TWMessage )
{
case MSG_XFERREADY:
{
ULONG nEvent = TWAIN_EVENT_QUIT;
if( 5 == nCurState )
{
nCurState = 6;
ImplXfer();
if( mxMgr.is() && mpMgr && mpMgr->GetData() )
2000-09-18 15:18:56 +00:00
nEvent = TWAIN_EVENT_XFER;
}
ImplFallback( nEvent );
}
break;
case MSG_CLOSEDSREQ:
ImplFallback( TWAIN_EVENT_QUIT );
break;
default:
break;
}
}
else
nRet = TWRC_NOTDSEVENT;
return( TWRC_DSEVENT == nRet );
}
// -----------------------------------------------------------------------------
void ImpTwain::ImplXfer()
{
if( nCurState == 6 )
{
TW_IMAGEINFO aInfo;
TW_UINT32 hDIB = 0;
long nWidth, nHeight, nXRes, nYRes;
if( PFUNC( &aAppIdent, &aSrcIdent, DG_IMAGE, DAT_IMAGEINFO, MSG_GET, &aInfo ) == TWRC_SUCCESS )
{
nWidth = aInfo.ImageWidth;
nHeight = aInfo.ImageLength;
nXRes = FIXTOLONG( aInfo.XResolution );
nYRes = FIXTOLONG( aInfo.YResolution );
}
else
nWidth = nHeight = nXRes = nYRes = -1L;
switch( PFUNC( &aAppIdent, &aSrcIdent, DG_IMAGE, DAT_IMAGENATIVEXFER, MSG_GET, &hDIB ) )
{
case( TWRC_CANCEL ):
nCurState = 7;
break;
case( TWRC_XFERDONE ):
{
if( mxMgr.is() && mpMgr && hDIB )
2000-09-18 15:18:56 +00:00
{
if( ( nXRes != -1 ) && ( nYRes != - 1 ) && ( nWidth != - 1 ) && ( nHeight != - 1 ) )
{
// set resolution of bitmap
BITMAPINFOHEADER* pBIH = (BITMAPINFOHEADER*) GlobalLock( (HGLOBAL) hDIB );
static const double fFactor = 100.0 / 2.54;
pBIH->biXPelsPerMeter = FRound( fFactor * nXRes );
pBIH->biYPelsPerMeter = FRound( fFactor * nYRes );
GlobalUnlock( (HGLOBAL) hDIB );
}
mpMgr->SetData( (void*)(long) hDIB );
}
else
GlobalFree( (HGLOBAL) hDIB );
nCurState = 7;
}
break;
default:
break;
}
}
}
// -----------------------------------------------------------------------------
void ImpTwain::ImplFallback( ULONG nEvent )
{
Application::PostUserEvent( LINK( this, ImpTwain, ImplFallbackHdl ), (void*) nEvent );
}
// -----------------------------------------------------------------------------
IMPL_LINK( ImpTwain, ImplFallbackHdl, void*, pData )
{
const ULONG nEvent = (ULONG) pData;
BOOL bFallback = TRUE;
switch( nCurState )
{
case( 7 ):
case( 6 ):
{
TW_PENDINGXFERS aXfers;
if( PFUNC( &aAppIdent, &aSrcIdent, DG_CONTROL, DAT_PENDINGXFERS, MSG_ENDXFER, &aXfers ) == TWRC_SUCCESS )
{
if( aXfers.Count != 0 )
PFUNC( &aAppIdent, &aSrcIdent, DG_CONTROL, DAT_PENDINGXFERS, MSG_RESET, &aXfers );
}
nCurState = 5;
}
break;
case( 5 ):
{
TW_USERINTERFACE aUI = { TRUE, TRUE, hTwainWnd };
PFUNC( &aAppIdent, &aSrcIdent, DG_CONTROL, DAT_USERINTERFACE, MSG_DISABLEDS, &aUI );
nCurState = 4;
// #107835# deregister as vetoable close listener
ImplDeregisterCloseListener();
2000-09-18 15:18:56 +00:00
}
break;
case( 4 ):
{
PFUNC( &aAppIdent, NULL, DG_CONTROL, DAT_IDENTITY, MSG_CLOSEDS, &aSrcIdent );
nCurState = 3;
}
break;
case( 3 ):
{
PFUNC( &aAppIdent, NULL, DG_CONTROL, DAT_PARENT, MSG_CLOSEDSM, &hTwainWnd );
nCurState = 2;
}
break;
case( 2 ):
{
delete pMod;
pMod = NULL;
nCurState = 1;
}
break;
default:
{
if( nEvent != TWAIN_EVENT_NONE )
aNotifyLink.Call( (void*) nEvent );
bFallback = FALSE;
}
break;
}
if( bFallback )
ImplFallback( nEvent );
return 0L;
}
// -----------------------------------------------------------------------------
IMPL_LINK( ImpTwain, ImplDestroyHdl, void*, p )
{
if( hTwainWnd )
DestroyWindow( hTwainWnd );
if( hTwainHook )
UnhookWindowsHookEx( hTwainHook );
// #107835# permit destruction of ourselves (normally, refcount
// should drop to zero exactly here)
mxSelfRef = NULL;
2000-09-18 15:18:56 +00:00
pImpTwainInstance = NULL;
return 0L;
}
// -----------------------------------------------------------------------------
uno::Reference< frame::XFrame > ImpTwain::ImplGetActiveFrame()
{
try
{
uno::Reference< lang::XMultiServiceFactory > xMgr( ::comphelper::getProcessServiceFactory() );
if( xMgr.is() )
{
// query desktop instance
uno::Reference< frame::XDesktop > xDesktop( xMgr->createInstance(
OUString::createFromAscii( "com.sun.star.frame.Desktop" ) ), uno::UNO_QUERY );
if( xDesktop.is() )
{
// query property set from desktop, which contains the currently active frame
uno::Reference< beans::XPropertySet > xDesktopProps( xDesktop, uno::UNO_QUERY );
if( xDesktopProps.is() )
{
uno::Any aActiveFrame;
try
{
aActiveFrame = xDesktopProps->getPropertyValue(
OUString::createFromAscii( "ActiveFrame" ) );
}
catch( const beans::UnknownPropertyException& )
{
// property unknown.
DBG_ERROR("ImpTwain::ImplGetActiveFrame: ActiveFrame property unknown, cannot determine active frame!");
return uno::Reference< frame::XFrame >();
}
uno::Reference< frame::XFrame > xActiveFrame;
if( (aActiveFrame >>= xActiveFrame) &&
xActiveFrame.is() )
{
return xActiveFrame;
}
}
}
}
}
catch( const uno::Exception& )
{
}
DBG_ERROR("ImpTwain::ImplGetActiveFrame: Could not determine active frame!");
return uno::Reference< frame::XFrame >();
}
// -----------------------------------------------------------------------------
uno::Reference< util::XCloseBroadcaster > ImpTwain::ImplGetActiveFrameCloseBroadcaster()
{
try
{
return uno::Reference< util::XCloseBroadcaster >( ImplGetActiveFrame(), uno::UNO_QUERY );
}
catch( const uno::Exception& )
{
}
DBG_ERROR("ImpTwain::ImplGetActiveFrameCloseBroadcaster: Could determine close broadcaster on active frame!");
return uno::Reference< util::XCloseBroadcaster >();
}
// -----------------------------------------------------------------------------
void ImpTwain::ImplRegisterCloseListener()
{
try
{
uno::Reference< util::XCloseBroadcaster > xCloseBroadcaster(
ImplGetActiveFrameCloseBroadcaster() );
if( xCloseBroadcaster.is() )
{
xCloseBroadcaster->addCloseListener(this);
return; // successfully registered as a close listener
}
else
{
// interface unknown. don't register, then
DBG_ERROR("ImpTwain::ImplRegisterCloseListener: XFrame has no XCloseBroadcaster!");
return;
}
}
catch( const uno::Exception& )
{
}
DBG_ERROR("ImpTwain::ImplRegisterCloseListener: Could not register as close listener!");
}
// -----------------------------------------------------------------------------
void ImpTwain::ImplDeregisterCloseListener()
{
try
{
uno::Reference< util::XCloseBroadcaster > xCloseBroadcaster(
ImplGetActiveFrameCloseBroadcaster() );
if( xCloseBroadcaster.is() )
{
xCloseBroadcaster->removeCloseListener(this);
return; // successfully deregistered as a close listener
}
else
{
// interface unknown. don't deregister, then
DBG_ERROR("ImpTwain::ImplDeregisterCloseListener: XFrame has no XCloseBroadcaster!");
return;
}
}
catch( const uno::Exception& )
{
}
DBG_ERROR("ImpTwain::ImplDeregisterCloseListener: Could not deregister as close listener!");
}
// -----------------------------------------------------------------------------
void SAL_CALL ImpTwain::queryClosing( const lang::EventObject& Source, sal_Bool GetsOwnership ) throw (util::CloseVetoException, uno::RuntimeException)
{
// shall we re-send the close query later on?
mbCloseFrameOnExit = GetsOwnership;
// the sole purpose of this listener is to forbid closing of the listened-at frame
throw util::CloseVetoException();
}
// -----------------------------------------------------------------------------
void SAL_CALL ImpTwain::notifyClosing( const lang::EventObject& Source ) throw (uno::RuntimeException)
{
// should not happen
DBG_ERROR("ImpTwain::notifyClosing called, but we vetoed the closing before!");
}
// -----------------------------------------------------------------------------
void SAL_CALL ImpTwain::disposing( const lang::EventObject& Source ) throw (uno::RuntimeException)
{
// we're not holding any references to the frame, thus noop
}
// -----------------------------------------------------------------------------
void ImpTwain::ImplSendCloseEvent()
{
try
{
uno::Reference< util::XCloseable > xCloseable( ImplGetActiveFrame(), uno::UNO_QUERY );
if( xCloseable.is() )
xCloseable->close( true );
}
catch( const uno::Exception& )
{
}
DBG_ERROR("ImpTwain::ImplSendCloseEvent: Could not send required close broadcast!");
}
2000-09-18 15:18:56 +00:00
// ---------
// - Twain -
// ---------
class Twain
{
REF( com::sun::star::scanner::XScannerManager ) mxMgr;
ScannerManager* mpMgr;
REF( com::sun::star::lang::XEventListener ) mxListener;
ImpTwain* mpImpTwain;
TwainState meState;
2000-09-18 15:18:56 +00:00
DECL_LINK( ImpNotifyHdl, ImpTwain* );
2000-09-18 15:18:56 +00:00
public:
Twain();
~Twain();
BOOL SelectSource();
BOOL PerformTransfer( ScannerManager* pMgr,
const REF( com::sun::star::lang::XEventListener )& rxListener );
TwainState GetState() const { return meState; }
};
// ------------------------------------------------------------------------
Twain::Twain() :
mxMgr (),
2000-09-18 15:18:56 +00:00
mpMgr ( NULL ),
mpImpTwain ( NULL ),
meState ( TWAIN_STATE_NONE )
{
}
// ------------------------------------------------------------------------
Twain::~Twain()
{
if( mpImpTwain )
mpImpTwain->Destroy();
}
// ------------------------------------------------------------------------
BOOL Twain::SelectSource()
{
BOOL bRet;
if( !mpImpTwain && mxMgr.is() )
2000-09-18 15:18:56 +00:00
{
meState = TWAIN_STATE_NONE;
mpImpTwain = new ImpTwain( mpMgr, LINK( this, Twain, ImpNotifyHdl ) );
bRet = mpImpTwain->SelectSource();
}
else
bRet = FALSE;
return bRet;
}
// ------------------------------------------------------------------------
BOOL Twain::PerformTransfer( ScannerManager* pMgr, const REF( com::sun::star::lang::XEventListener )& rxListener )
{
BOOL bRet;
if( pMgr && !mpImpTwain )
{
// #107835# hold reference to ScannerManager, to prevent premature death
mxMgr = REF(com::sun::star::scanner::XScannerManager)(static_cast< OWeakObject* >(pMgr),
::com::sun::star::uno::UNO_QUERY),
2000-09-18 15:18:56 +00:00
mpMgr = pMgr;
mxListener = rxListener;
meState = TWAIN_STATE_NONE;
mpImpTwain = new ImpTwain( mpMgr, LINK( this, Twain, ImpNotifyHdl ) );
bRet = mpImpTwain->InitXfer();
}
else
bRet = FALSE;
return bRet;
}
// ------------------------------------------------------------------------
IMPL_LINK( Twain, ImpNotifyHdl, ImpTwain*, nEvent )
{
switch( (ULONG)(void*) nEvent )
{
case( TWAIN_EVENT_SCANNING ):
meState = TWAIN_STATE_SCANNING;
break;
case( TWAIN_EVENT_QUIT ):
{
if( meState != TWAIN_STATE_DONE )
meState = TWAIN_STATE_CANCELED;
2002-11-05 11:02:56 +00:00
if( mpImpTwain )
{
mpImpTwain->Destroy();
mpImpTwain = NULL;
}
2000-09-18 15:18:56 +00:00
if( mxMgr.is() && mpMgr && mxListener.is() )
2000-09-18 15:18:56 +00:00
mxListener->disposing( com::sun::star::lang::EventObject( REF( XInterface )( static_cast< OWeakObject* >( mpMgr ) ) ) );
mxListener = REF( com::sun::star::lang::XEventListener )();
}
break;
case( TWAIN_EVENT_XFER ):
{
if( mxMgr.is() && mpMgr && mpImpTwain )
2000-09-18 15:18:56 +00:00
{
meState = ( ( mpMgr && mpMgr->GetData() ) ? TWAIN_STATE_DONE : TWAIN_STATE_CANCELED );
mpImpTwain->Destroy();
mpImpTwain = NULL;
if( mpMgr && mxListener.is() )
mxListener->disposing( com::sun::star::lang::EventObject( REF( XInterface )( static_cast< OWeakObject* >( mpMgr ) ) ) );
}
mxListener = REF( com::sun::star::lang::XEventListener )();
}
break;
default:
break;
}
return 0L;
}
// -----------
// - statics -
// -----------
static Twain aTwain;
// ------------------
// - ScannerManager -
// ------------------
void ScannerManager::DestroyData()
{
if( mpData )
{
GlobalFree( (HGLOBAL)(long) mpData );
mpData = NULL;
}
}
// -----------------------------------------------------------------------------
AWT::Size ScannerManager::getSize()
{
AWT::Size aRet;
HGLOBAL hDIB = (HGLOBAL)(long) mpData;
if( hDIB )
{
BITMAPINFOHEADER* pBIH = (BITMAPINFOHEADER*) GlobalLock( hDIB );
if( pBIH )
{
aRet.Width = pBIH->biWidth;
aRet.Height = pBIH->biHeight;
}
else
aRet.Width = aRet.Height = 0;
GlobalUnlock( hDIB );
}
else
aRet.Width = aRet.Height = 0;
return aRet;
}
// -----------------------------------------------------------------------------
SEQ( sal_Int8 ) ScannerManager::getDIB()
{
SEQ( sal_Int8 ) aRet;
if( mpData )
{
HGLOBAL hDIB = (HGLOBAL)(long) mpData;
const sal_uInt32 nDIBSize = GlobalSize( hDIB );
sal_uInt32 nSize = sizeof( BITMAPFILEHEADER) + nDIBSize;
BITMAPINFOHEADER* pBIH = (BITMAPINFOHEADER*) GlobalLock( hDIB );
if( pBIH )
{
sal_uInt32 nColEntries;
switch( pBIH->biBitCount )
{
case( 1 ):
case( 4 ):
case( 8 ):
nColEntries = pBIH->biClrUsed ? pBIH->biClrUsed : ( 1 << pBIH->biBitCount );
break;
case( 24 ):
nColEntries = pBIH->biClrUsed ? pBIH->biClrUsed : 0;
break;
case( 16 ):
case( 32 ):
{
nColEntries = pBIH->biClrUsed;
if( pBIH->biCompression == BI_BITFIELDS )
nColEntries += 3;
}
break;
default:
nColEntries = 0;
break;
}
aRet = SEQ( sal_Int8 )( sizeof( BITMAPFILEHEADER ) + nDIBSize );
sal_Int8* pBuf = aRet.getArray();
SvMemoryStream* pMemStm = new SvMemoryStream( (char*) pBuf, sizeof( BITMAPFILEHEADER ), STREAM_WRITE );
*pMemStm << 'B' << 'M' << (sal_uInt32) 0 << (sal_uInt32) 0;
*pMemStm << (sal_uInt32) ( sizeof( BITMAPFILEHEADER ) + pBIH->biSize + ( nColEntries * sizeof( RGBQUAD ) ) );
delete pMemStm;
memcpy( pBuf + sizeof( BITMAPFILEHEADER ), pBIH, nDIBSize );
2000-09-18 15:18:56 +00:00
}
GlobalUnlock( hDIB );
DestroyData();
}
return aRet;
}
// -----------------------------------------------------------------------------
SEQ( ScannerContext ) SAL_CALL ScannerManager::getAvailableScanners()
{
vos::OGuard aGuard( maProtector );
SEQ( ScannerContext ) aRet( 1 );
aRet.getArray()[0].ScannerName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "TWAIN" ) );
aRet.getArray()[0].InternalData = 0;
return aRet;
}
// -----------------------------------------------------------------------------
BOOL SAL_CALL ScannerManager::configureScanner( ScannerContext& rContext ) throw( ScannerException )
{
vos::OGuard aGuard( maProtector );
REF( XScannerManager ) xThis( this );
if( rContext.InternalData != 0 || rContext.ScannerName != ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "TWAIN" ) ) )
throw ScannerException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Scanner does not exist" ) ), xThis, ScanError_InvalidContext );
DestroyData();
return aTwain.SelectSource();
}
// -----------------------------------------------------------------------------
void SAL_CALL ScannerManager::startScan( const ScannerContext& rContext, const REF( com::sun::star::lang::XEventListener )& rxListener ) throw( ScannerException )
{
vos::OGuard aGuard( maProtector );
REF( XScannerManager ) xThis( this );
if( rContext.InternalData != 0 || rContext.ScannerName != ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "TWAIN" ) ) )
throw ScannerException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Scanner does not exist" ) ), xThis, ScanError_InvalidContext );
DestroyData();
aTwain.PerformTransfer( this, rxListener );
}
// -----------------------------------------------------------------------------
ScanError SAL_CALL ScannerManager::getError( const ScannerContext& rContext ) throw( ScannerException )
{
vos::OGuard aGuard( maProtector );
ScanError eError;
REF( XScannerManager ) xThis( this );
if( rContext.InternalData != 0 || rContext.ScannerName != ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "TWAIN" ) ) )
throw ScannerException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Scanner does not exist" ) ), xThis, ScanError_InvalidContext );
if( aTwain.GetState() == TWAIN_STATE_CANCELED )
eError = ScanError_ScanCanceled;
else
eError = ScanError_ScanErrorNone;
return eError;
}
// -----------------------------------------------------------------------------
REF( AWT::XBitmap ) SAL_CALL ScannerManager::getBitmap( const ScannerContext& rContext ) throw( ScannerException )
{
vos::OGuard aGuard( maProtector );
return REF( AWT::XBitmap )( this );
}