Update ooo320-m1
[ooovba.git] / extensions / source / scanner / twain.cxx
blobdec87a3abddbe7394a5005cad048f4123d6820da
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: twain.cxx,v $
10 * $Revision: 1.6 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_extensions.hxx"
34 #include <string.h>
35 #include <math.h>
37 #if defined( WNT ) || defined (WIN)
38 #include <tools/svwin.h>
39 #endif
40 #ifdef OS2
41 #include <svpm.h>
42 #endif // OS2
43 #include <vos/module.hxx>
44 #include <tools/stream.hxx>
45 #include <vcl/svapp.hxx>
46 #include <vcl/wrkwin.hxx>
47 #include <vcl/sysdata.hxx>
48 #include "twain.hxx"
50 // -----------
51 // - Defines -
52 // -----------
54 #define PFUNC (*pDSM)
55 #define FIXTODOUBLE( nFix ) ((double)nFix.Whole+(double)nFix.Frac/65536.)
56 #define FIXTOLONG( nFix ) ((long)floor(FIXTODOUBLE(nFix)+0.5))
58 #if defined WIN
59 #define TWAIN_LIBNAME "TWAIN.DLL"
60 #define TWAIN_FUNCNAME "DSM_Entry"
61 #elif defined WNT
62 #define TWAIN_LIBNAME "TWAIN_32.DLL"
63 #define TWAIN_FUNCNAME "DSM_Entry"
64 #elif defined OS2
65 #define TWAIN_LIBNAME "twain"
66 #define TWAIN_FUNCNAME "DSM_ENTRY"
67 #endif
69 // -----------
70 // - Statics -
71 // -----------
73 static ImpTwain* pImpTwainInstance = NULL;
75 // ---------
76 // - Procs -
77 // ---------
79 #ifdef OS2
81 #define PTWAINMSG QMSG*
83 MRESULT EXPENTRY TwainWndProc( HWND hWnd, ULONG nMsg, MPARAM nParam1, MPARAM nParam2 )
85 return (MRESULT) TRUE;
89 #else // OS2
91 #define PTWAINMSG MSG*
93 // -------------------------------------------------------------------------
95 LRESULT CALLBACK TwainWndProc( HWND hWnd,UINT nMsg, WPARAM nPar1, LPARAM nPar2 )
97 return DefWindowProc( hWnd, nMsg, nPar1, nPar2 );
100 // -------------------------------------------------------------------------
102 LRESULT CALLBACK TwainMsgProc( int nCode, WPARAM wParam, LPARAM lParam )
104 MSG* pMsg = (MSG*) lParam;
106 if( ( nCode < 0 ) ||
107 ( pImpTwainInstance->hTwainWnd != pMsg->hwnd ) ||
108 !pImpTwainInstance->ImplHandleMsg( (void*) lParam ) )
110 return CallNextHookEx( pImpTwainInstance->hTwainHook, nCode, wParam, lParam );
112 else
114 pMsg->message = WM_USER;
115 pMsg->lParam = 0;
117 return 0;
121 #endif // OS2
123 // ------------
124 // - ImpTwain -
125 // ------------
127 ImpTwain::ImpTwain( const Link& rNotifyLink ) :
128 aNotifyLink ( rNotifyLink ),
129 pDSM ( NULL ),
130 pMod ( NULL ),
131 hTwainWnd ( 0 ),
132 hTwainHook ( 0 ),
133 nCurState ( 1 )
135 pImpTwainInstance = this;
137 aAppIdent.Id = 0;
138 aAppIdent.Version.MajorNum = 1;
139 aAppIdent.Version.MinorNum = 0;
140 aAppIdent.Version.Language = TWLG_USA;
141 aAppIdent.Version.Country = TWCY_USA;
142 aAppIdent.ProtocolMajor = TWON_PROTOCOLMAJOR;
143 aAppIdent.ProtocolMinor = TWON_PROTOCOLMINOR;
144 aAppIdent.SupportedGroups = DG_IMAGE | DG_CONTROL;
145 strcpy( aAppIdent.Version.Info, "6.0" );
146 strcpy( aAppIdent.Manufacturer, "Sun Microsystems");
147 strcpy( aAppIdent.ProductFamily,"Office");
148 strcpy( aAppIdent.ProductName, "Office");
150 #ifdef OS2
152 hAB = Sysdepen::GethAB();
153 ImplFallback( TWAIN_EVENT_QUIT );
154 // hTwainWnd = WinCreateWindow( HWND_DESKTOP, WC_FRAME, "dummy", 0, 0, 0, 0, 0, HWND_DESKTOP, HWND_BOTTOM, 0, 0, 0 );
156 #else
158 HWND hParentWnd = HWND_DESKTOP;
159 WNDCLASS aWc = { 0, &TwainWndProc, 0, sizeof( WNDCLASS ), GetModuleHandle( NULL ),
160 NULL, NULL, NULL, NULL, "TwainClass" };
162 RegisterClass( &aWc );
163 hTwainWnd = CreateWindowEx( WS_EX_TOPMOST, aWc.lpszClassName, "TWAIN", 0, 0, 0, 0, 0, hParentWnd, NULL, aWc.hInstance, 0 );
164 hTwainHook = SetWindowsHookEx( WH_GETMESSAGE, &TwainMsgProc, NULL, GetCurrentThreadId() );
166 #endif
169 // -----------------------------------------------------------------------------
171 ImpTwain::~ImpTwain()
175 // -----------------------------------------------------------------------------
177 void ImpTwain::Destroy()
179 ImplFallback( TWAIN_EVENT_NONE );
180 Application::PostUserEvent( LINK( this, ImpTwain, ImplDestroyHdl ), NULL );
183 // -----------------------------------------------------------------------------
185 BOOL ImpTwain::SelectSource()
187 TW_UINT16 nRet = TWRC_FAILURE;
189 if( !!aBitmap )
190 aBitmap = Bitmap();
192 ImplOpenSourceManager();
194 if( 3 == nCurState )
196 TW_IDENTITY aIdent;
198 aIdent.Id = 0, aIdent.ProductName[ 0 ] = '\0';
199 aNotifyLink.Call( (void*) TWAIN_EVENT_SCANNING );
200 nRet = PFUNC( &aAppIdent, NULL, DG_CONTROL, DAT_IDENTITY, MSG_USERSELECT, &aIdent );
203 ImplFallback( TWAIN_EVENT_QUIT );
205 return( nRet == TWRC_SUCCESS || nRet == TWRC_CANCEL );
208 // -----------------------------------------------------------------------------
210 BOOL ImpTwain::InitXfer()
212 BOOL bRet = FALSE;
214 if( !!aBitmap )
215 aBitmap = Bitmap();
217 ImplOpenSourceManager();
219 if( 3 == nCurState )
221 ImplOpenSource();
223 if( 4 == nCurState )
224 bRet = ImplEnableSource();
227 if( !bRet )
228 ImplFallback( TWAIN_EVENT_QUIT );
230 return bRet;
233 // -----------------------------------------------------------------------------
235 Bitmap ImpTwain::GetXferBitmap()
237 Bitmap aRet( aBitmap );
238 aBitmap = Bitmap();
239 return aRet;
242 // -----------------------------------------------------------------------------
244 void ImpTwain::ImplOpenSourceManager()
246 if( 1 == nCurState )
248 pMod = new NAMESPACE_VOS( OModule )();
250 if( pMod->load( TWAIN_LIBNAME ) )
252 nCurState = 2;
254 if( ( ( pDSM = (DSMENTRYPROC) pMod->getSymbol( TWAIN_FUNCNAME ) ) != NULL ) &&
255 ( PFUNC( &aAppIdent, NULL, DG_CONTROL, DAT_PARENT, MSG_OPENDSM, &hTwainWnd ) == TWRC_SUCCESS ) )
257 nCurState = 3;
260 else
262 delete pMod;
263 pMod = NULL;
268 // -----------------------------------------------------------------------------
270 void ImpTwain::ImplOpenSource()
272 if( 3 == nCurState )
274 if( ( PFUNC( &aAppIdent, NULL, DG_CONTROL, DAT_IDENTITY, MSG_GETDEFAULT, &aSrcIdent ) == TWRC_SUCCESS ) &&
275 ( PFUNC( &aAppIdent, NULL, DG_CONTROL, DAT_IDENTITY, MSG_OPENDS, &aSrcIdent ) == TWRC_SUCCESS ) )
277 #ifdef OS2
279 // negotiate capabilities
281 #else
283 TW_CAPABILITY aCap = { CAP_XFERCOUNT, TWON_ONEVALUE, GlobalAlloc( GHND, sizeof( TW_ONEVALUE ) ) };
284 TW_ONEVALUE* pVal = (TW_ONEVALUE*) GlobalLock( aCap.hContainer );
286 pVal->ItemType = TWTY_INT16, pVal->Item = 1;
287 GlobalUnlock( aCap.hContainer );
288 PFUNC( &aAppIdent, &aSrcIdent, DG_CONTROL, DAT_CAPABILITY, MSG_SET, &aCap );
289 GlobalFree( aCap.hContainer );
290 #endif
292 nCurState = 4;
297 // -----------------------------------------------------------------------------
299 BOOL ImpTwain::ImplEnableSource()
301 BOOL bRet = FALSE;
303 if( 4 == nCurState )
305 TW_USERINTERFACE aUI = { TRUE, TRUE, hTwainWnd };
307 aNotifyLink.Call( (void*) TWAIN_EVENT_SCANNING );
308 nCurState = 5;
310 if( PFUNC( &aAppIdent, &aSrcIdent, DG_CONTROL, DAT_USERINTERFACE, MSG_ENABLEDS, &aUI ) == TWRC_SUCCESS )
311 bRet = TRUE;
312 else
313 nCurState = 4;
316 return bRet;
319 // -----------------------------------------------------------------------------
321 BOOL ImpTwain::ImplHandleMsg( void* pMsg )
323 TW_UINT16 nRet;
324 PTWAINMSG pMess = (PTWAINMSG) pMsg;
325 TW_EVENT aEvt = { pMess, MSG_NULL };
327 nRet = PFUNC( &aAppIdent, &aSrcIdent, DG_CONTROL, DAT_EVENT, MSG_PROCESSEVENT, &aEvt );
329 if( aEvt.TWMessage != MSG_NULL )
331 switch( aEvt.TWMessage )
333 case MSG_XFERREADY:
335 ULONG nEvent = TWAIN_EVENT_QUIT;
337 if( 5 == nCurState )
339 nCurState = 6;
340 ImplXfer();
342 if( !!aBitmap )
343 nEvent = TWAIN_EVENT_XFER;
346 ImplFallback( nEvent );
348 break;
350 case MSG_CLOSEDSREQ:
351 ImplFallback( TWAIN_EVENT_QUIT );
352 break;
354 default:
355 break;
358 else
359 nRet = TWRC_NOTDSEVENT;
361 return( TWRC_DSEVENT == nRet );
364 // -----------------------------------------------------------------------------
366 void ImpTwain::ImplXfer()
368 if( nCurState == 6 )
370 TW_IMAGEINFO aInfo;
371 TW_UINT32 hDIB = 0;
372 long nWidth = aInfo.ImageWidth;
373 long nHeight = aInfo.ImageLength;
374 long nXRes = FIXTOLONG( aInfo.XResolution );
375 long nYRes = FIXTOLONG( aInfo.YResolution );
377 if( PFUNC( &aAppIdent, &aSrcIdent, DG_IMAGE, DAT_IMAGEINFO, MSG_GET, &aInfo ) == TWRC_SUCCESS )
379 nWidth = aInfo.ImageWidth;
380 nHeight = aInfo.ImageLength;
381 nXRes = FIXTOLONG( aInfo.XResolution );
382 nYRes = FIXTOLONG( aInfo.YResolution );
384 else
385 nWidth = nHeight = nXRes = nYRes = -1L;
387 switch( PFUNC( &aAppIdent, &aSrcIdent, DG_IMAGE, DAT_IMAGENATIVEXFER, MSG_GET, &hDIB ) )
389 case( TWRC_CANCEL ):
390 nCurState = 7;
391 break;
393 case( TWRC_XFERDONE ):
395 #ifdef OS2
397 // get OS/2-Bitmap
399 #else // OS2
400 const ULONG nSize = GlobalSize( (HGLOBAL) hDIB );
401 char* pBuf = (char*) GlobalLock( (HGLOBAL) hDIB );
403 if( pBuf )
405 SvMemoryStream aMemStm;
406 aMemStm.SetBuffer( pBuf, nSize, FALSE, nSize );
407 aBitmap.Read( aMemStm, FALSE );
408 GlobalUnlock( (HGLOBAL) hDIB );
411 GlobalFree( (HGLOBAL) hDIB );
412 #endif // OS2
414 // set resolution of bitmap if neccessary
415 if ( ( nXRes != -1 ) && ( nYRes != - 1 ) && ( nWidth != - 1 ) && ( nHeight != - 1 ) )
417 const MapMode aMapMode( MAP_100TH_INCH, Point(), Fraction( 100, nXRes ), Fraction( 100, nYRes ) );
418 aBitmap.SetPrefMapMode( aMapMode );
419 aBitmap.SetPrefSize( Size( nWidth, nHeight ) );
422 nCurState = 7;
424 break;
426 default:
427 break;
432 // -----------------------------------------------------------------------------
434 void ImpTwain::ImplFallback( ULONG nEvent )
436 Application::PostUserEvent( LINK( this, ImpTwain, ImplFallbackHdl ), (void*) nEvent );
439 // -----------------------------------------------------------------------------
441 IMPL_LINK( ImpTwain, ImplFallbackHdl, void*, pData )
443 const ULONG nEvent = (ULONG) pData;
444 BOOL bFallback = TRUE;
446 switch( nCurState )
448 case( 7 ):
449 case( 6 ):
451 TW_PENDINGXFERS aXfers;
453 if( PFUNC( &aAppIdent, &aSrcIdent, DG_CONTROL, DAT_PENDINGXFERS, MSG_ENDXFER, &aXfers ) == TWRC_SUCCESS )
455 if( aXfers.Count != 0 )
456 PFUNC( &aAppIdent, &aSrcIdent, DG_CONTROL, DAT_PENDINGXFERS, MSG_RESET, &aXfers );
459 nCurState = 5;
461 break;
463 case( 5 ):
465 TW_USERINTERFACE aUI = { TRUE, TRUE, hTwainWnd };
467 PFUNC( &aAppIdent, &aSrcIdent, DG_CONTROL, DAT_USERINTERFACE, MSG_DISABLEDS, &aUI );
468 nCurState = 4;
470 break;
472 case( 4 ):
474 PFUNC( &aAppIdent, NULL, DG_CONTROL, DAT_IDENTITY, MSG_CLOSEDS, &aSrcIdent );
475 nCurState = 3;
477 break;
479 case( 3 ):
481 PFUNC( &aAppIdent, NULL, DG_CONTROL, DAT_PARENT, MSG_CLOSEDSM, &hTwainWnd );
482 nCurState = 2;
484 break;
486 case( 2 ):
488 delete pMod;
489 pMod = NULL;
490 nCurState = 1;
492 break;
494 default:
496 if( nEvent != TWAIN_EVENT_NONE )
497 aNotifyLink.Call( (void*) nEvent );
499 bFallback = FALSE;
501 break;
504 if( bFallback )
505 ImplFallback( nEvent );
507 return 0L;
510 // -----------------------------------------------------------------------------
512 IMPL_LINK( ImpTwain, ImplDestroyHdl, void*, p )
514 #ifdef OS2
516 if( hWndTwain )
517 WinDestroyWindow( hWndTwain );
519 // unset hook
521 #else
523 if( hTwainWnd )
524 DestroyWindow( hTwainWnd );
526 if( hTwainHook )
527 UnhookWindowsHookEx( hTwainHook );
529 #endif
531 delete this;
532 pImpTwainInstance = NULL;
534 return 0L;