blob: 154f64984e13c1c2d138d4ef8df594afc4ca5aab [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_extensions.hxx"
#include <string.h>
#include <math.h>
#if defined( WNT )
#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 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 );
}
// -----------------------------------------------------------------------------
sal_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 );
}
// -----------------------------------------------------------------------------
sal_Bool ImpTwain::InitXfer()
{
sal_Bool bRet = sal_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 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;
sal_Bool bFallback = sal_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 = sal_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;
}