diff options
Diffstat (limited to 'extensions/source/scanner/twain.cxx')
-rw-r--r-- | extensions/source/scanner/twain.cxx | 535 |
1 files changed, 535 insertions, 0 deletions
diff --git a/extensions/source/scanner/twain.cxx b/extensions/source/scanner/twain.cxx new file mode 100644 index 000000000000..a42e178e2cc3 --- /dev/null +++ b/extensions/source/scanner/twain.cxx @@ -0,0 +1,535 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: twain.cxx,v $ + * $Revision: 1.6 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_extensions.hxx" + +#include <string.h> +#include <math.h> + +#if defined( WNT ) || defined (WIN) +#include <tools/svwin.h> +#endif +#ifdef OS2 +#include <svpm.h> +#endif // OS2 +#include <vos/module.hxx> +#include <tools/stream.hxx> +#include <vcl/svapp.hxx> +#include <vcl/wrkwin.hxx> +#include <vcl/sysdata.hxx> +#include "twain.hxx" + +// ----------- +// - Defines - +// ----------- + +#define PFUNC (*pDSM) +#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" +#elif defined OS2 +#define TWAIN_LIBNAME "twain" +#define TWAIN_FUNCNAME "DSM_ENTRY" +#endif + +// ----------- +// - Statics - +// ----------- + +static ImpTwain* pImpTwainInstance = NULL; + +// --------- +// - Procs - +// --------- + +#ifdef OS2 + + #define PTWAINMSG QMSG* + + MRESULT EXPENTRY TwainWndProc( HWND hWnd, ULONG nMsg, MPARAM nParam1, MPARAM nParam2 ) + { + return (MRESULT) TRUE; + } + + +#else // OS2 + + #define PTWAINMSG MSG* + + // ------------------------------------------------------------------------- + + 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; + } + } + +#endif // OS2 + +// ------------ +// - ImpTwain - +// ------------ + +ImpTwain::ImpTwain( const Link& rNotifyLink ) : + aNotifyLink ( rNotifyLink ), + pDSM ( NULL ), + pMod ( NULL ), + hTwainWnd ( 0 ), + hTwainHook ( 0 ), + nCurState ( 1 ) +{ + 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; + strcpy( aAppIdent.Version.Info, "6.0" ); + strcpy( aAppIdent.Manufacturer, "Sun Microsystems"); + strcpy( aAppIdent.ProductFamily,"Office"); + strcpy( aAppIdent.ProductName, "Office"); + +#ifdef OS2 + + hAB = Sysdepen::GethAB(); + ImplFallback( TWAIN_EVENT_QUIT ); + // hTwainWnd = WinCreateWindow( HWND_DESKTOP, WC_FRAME, "dummy", 0, 0, 0, 0, 0, HWND_DESKTOP, HWND_BOTTOM, 0, 0, 0 ); + +#else + + HWND hParentWnd = HWND_DESKTOP; + 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() ); + +#endif +} + +// ----------------------------------------------------------------------------- + +ImpTwain::~ImpTwain() +{ +} + +// ----------------------------------------------------------------------------- + +void ImpTwain::Destroy() +{ + ImplFallback( TWAIN_EVENT_NONE ); + Application::PostUserEvent( LINK( this, ImpTwain, ImplDestroyHdl ), NULL ); +} + +// ----------------------------------------------------------------------------- + +BOOL ImpTwain::SelectSource() +{ + TW_UINT16 nRet = TWRC_FAILURE; + + if( !!aBitmap ) + aBitmap = Bitmap(); + + 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( nRet == TWRC_SUCCESS || nRet == TWRC_CANCEL ); +} + +// ----------------------------------------------------------------------------- + +BOOL ImpTwain::InitXfer() +{ + BOOL bRet = FALSE; + + if( !!aBitmap ) + aBitmap = Bitmap(); + + ImplOpenSourceManager(); + + if( 3 == nCurState ) + { + ImplOpenSource(); + + if( 4 == nCurState ) + bRet = ImplEnableSource(); + } + + if( !bRet ) + ImplFallback( TWAIN_EVENT_QUIT ); + + return bRet; +} + +// ----------------------------------------------------------------------------- + +Bitmap ImpTwain::GetXferBitmap() +{ + Bitmap aRet( aBitmap ); + aBitmap = Bitmap(); + return aRet; +} + +// ----------------------------------------------------------------------------- + +void ImpTwain::ImplOpenSourceManager() +{ + if( 1 == nCurState ) + { + pMod = new NAMESPACE_VOS( OModule )(); + + if( pMod->load( TWAIN_LIBNAME ) ) + { + nCurState = 2; + + if( ( ( pDSM = (DSMENTRYPROC) pMod->getSymbol( 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 ) ) + { +#ifdef OS2 + + // negotiate capabilities + +#else + + 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 ); +#endif + + 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; + + if( PFUNC( &aAppIdent, &aSrcIdent, DG_CONTROL, DAT_USERINTERFACE, MSG_ENABLEDS, &aUI ) == TWRC_SUCCESS ) + bRet = TRUE; + else + nCurState = 4; + } + + 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( !!aBitmap ) + 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 = aInfo.ImageWidth; + long nHeight = aInfo.ImageLength; + long nXRes = FIXTOLONG( aInfo.XResolution ); + long nYRes = FIXTOLONG( aInfo.YResolution ); + + 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 ): + { +#ifdef OS2 + + // get OS/2-Bitmap + +#else // OS2 + const ULONG nSize = GlobalSize( (HGLOBAL) hDIB ); + char* pBuf = (char*) GlobalLock( (HGLOBAL) hDIB ); + + if( pBuf ) + { + SvMemoryStream aMemStm; + aMemStm.SetBuffer( pBuf, nSize, FALSE, nSize ); + aBitmap.Read( aMemStm, FALSE ); + GlobalUnlock( (HGLOBAL) hDIB ); + } + + GlobalFree( (HGLOBAL) hDIB ); +#endif // OS2 + + // set resolution of bitmap if neccessary + if ( ( nXRes != -1 ) && ( nYRes != - 1 ) && ( nWidth != - 1 ) && ( nHeight != - 1 ) ) + { + const MapMode aMapMode( MAP_100TH_INCH, Point(), Fraction( 100, nXRes ), Fraction( 100, nYRes ) ); + aBitmap.SetPrefMapMode( aMapMode ); + aBitmap.SetPrefSize( Size( nWidth, nHeight ) ); + } + + 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; + } + 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 ) +{ +#ifdef OS2 + + if( hWndTwain ) + WinDestroyWindow( hWndTwain ); + + // unset hook + +#else + + if( hTwainWnd ) + DestroyWindow( hTwainWnd ); + + if( hTwainHook ) + UnhookWindowsHookEx( hTwainHook ); + +#endif + + delete this; + pImpTwainInstance = NULL; + + return 0L; +} |