merged tag ooo/OOO330_m14
[LibreOffice.git] / extensions / source / scanner / twain.cxx
blobb11f2725501e682c8ce85d136f35db1e36c22d94
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
11 * OpenOffice.org is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License version 3
13 * only, as published by the Free Software Foundation.
15 * OpenOffice.org is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License version 3 for more details
19 * (a copy is included in the LICENSE file that accompanied this code).
21 * You should have received a copy of the GNU Lesser General Public License
22 * version 3 along with OpenOffice.org. If not, see
23 * <http://www.openoffice.org/license.html>
24 * for a copy of the LGPLv3 License.
26 ************************************************************************/
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_extensions.hxx"
31 #include <string.h>
32 #include <math.h>
34 #if defined( WNT ) || defined (WIN)
35 #include <tools/svwin.h>
36 #endif
37 #ifdef OS2
38 #include <svpm.h>
39 #endif // OS2
40 #include <vos/module.hxx>
41 #include <tools/stream.hxx>
42 #include <vcl/svapp.hxx>
43 #include <vcl/wrkwin.hxx>
44 #include <vcl/sysdata.hxx>
45 #include "twain.hxx"
47 // -----------
48 // - Defines -
49 // -----------
51 #define PFUNC (*pDSM)
52 #define FIXTODOUBLE( nFix ) ((double)nFix.Whole+(double)nFix.Frac/65536.)
53 #define FIXTOLONG( nFix ) ((long)floor(FIXTODOUBLE(nFix)+0.5))
55 #if defined WIN
56 #define TWAIN_LIBNAME "TWAIN.DLL"
57 #define TWAIN_FUNCNAME "DSM_Entry"
58 #elif defined WNT
59 #define TWAIN_LIBNAME "TWAIN_32.DLL"
60 #define TWAIN_FUNCNAME "DSM_Entry"
61 #elif defined OS2
62 #define TWAIN_LIBNAME "twain"
63 #define TWAIN_FUNCNAME "DSM_ENTRY"
64 #endif
66 // -----------
67 // - Statics -
68 // -----------
70 static ImpTwain* pImpTwainInstance = NULL;
72 // ---------
73 // - Procs -
74 // ---------
76 #ifdef OS2
78 #define PTWAINMSG QMSG*
80 MRESULT EXPENTRY TwainWndProc( HWND hWnd, ULONG nMsg, MPARAM nParam1, MPARAM nParam2 )
82 return (MRESULT) TRUE;
86 #else // OS2
88 #define PTWAINMSG MSG*
90 // -------------------------------------------------------------------------
92 LRESULT CALLBACK TwainWndProc( HWND hWnd,UINT nMsg, WPARAM nPar1, LPARAM nPar2 )
94 return DefWindowProc( hWnd, nMsg, nPar1, nPar2 );
97 // -------------------------------------------------------------------------
99 LRESULT CALLBACK TwainMsgProc( int nCode, WPARAM wParam, LPARAM lParam )
101 MSG* pMsg = (MSG*) lParam;
103 if( ( nCode < 0 ) ||
104 ( pImpTwainInstance->hTwainWnd != pMsg->hwnd ) ||
105 !pImpTwainInstance->ImplHandleMsg( (void*) lParam ) )
107 return CallNextHookEx( pImpTwainInstance->hTwainHook, nCode, wParam, lParam );
109 else
111 pMsg->message = WM_USER;
112 pMsg->lParam = 0;
114 return 0;
118 #endif // OS2
120 // ------------
121 // - ImpTwain -
122 // ------------
124 ImpTwain::ImpTwain( const Link& rNotifyLink ) :
125 aNotifyLink ( rNotifyLink ),
126 pDSM ( NULL ),
127 pMod ( NULL ),
128 hTwainWnd ( 0 ),
129 hTwainHook ( 0 ),
130 nCurState ( 1 )
132 pImpTwainInstance = this;
134 aAppIdent.Id = 0;
135 aAppIdent.Version.MajorNum = 1;
136 aAppIdent.Version.MinorNum = 0;
137 aAppIdent.Version.Language = TWLG_USA;
138 aAppIdent.Version.Country = TWCY_USA;
139 aAppIdent.ProtocolMajor = TWON_PROTOCOLMAJOR;
140 aAppIdent.ProtocolMinor = TWON_PROTOCOLMINOR;
141 aAppIdent.SupportedGroups = DG_IMAGE | DG_CONTROL;
142 strcpy( aAppIdent.Version.Info, "6.0" );
143 strcpy( aAppIdent.Manufacturer, "Sun Microsystems");
144 strcpy( aAppIdent.ProductFamily,"Office");
145 strcpy( aAppIdent.ProductName, "Office");
147 #ifdef OS2
149 hAB = Sysdepen::GethAB();
150 ImplFallback( TWAIN_EVENT_QUIT );
151 // hTwainWnd = WinCreateWindow( HWND_DESKTOP, WC_FRAME, "dummy", 0, 0, 0, 0, 0, HWND_DESKTOP, HWND_BOTTOM, 0, 0, 0 );
153 #else
155 HWND hParentWnd = HWND_DESKTOP;
156 WNDCLASS aWc = { 0, &TwainWndProc, 0, sizeof( WNDCLASS ), GetModuleHandle( NULL ),
157 NULL, NULL, NULL, NULL, "TwainClass" };
159 RegisterClass( &aWc );
160 hTwainWnd = CreateWindowEx( WS_EX_TOPMOST, aWc.lpszClassName, "TWAIN", 0, 0, 0, 0, 0, hParentWnd, NULL, aWc.hInstance, 0 );
161 hTwainHook = SetWindowsHookEx( WH_GETMESSAGE, &TwainMsgProc, NULL, GetCurrentThreadId() );
163 #endif
166 // -----------------------------------------------------------------------------
168 ImpTwain::~ImpTwain()
172 // -----------------------------------------------------------------------------
174 void ImpTwain::Destroy()
176 ImplFallback( TWAIN_EVENT_NONE );
177 Application::PostUserEvent( LINK( this, ImpTwain, ImplDestroyHdl ), NULL );
180 // -----------------------------------------------------------------------------
182 BOOL ImpTwain::SelectSource()
184 TW_UINT16 nRet = TWRC_FAILURE;
186 if( !!aBitmap )
187 aBitmap = Bitmap();
189 ImplOpenSourceManager();
191 if( 3 == nCurState )
193 TW_IDENTITY aIdent;
195 aIdent.Id = 0, aIdent.ProductName[ 0 ] = '\0';
196 aNotifyLink.Call( (void*) TWAIN_EVENT_SCANNING );
197 nRet = PFUNC( &aAppIdent, NULL, DG_CONTROL, DAT_IDENTITY, MSG_USERSELECT, &aIdent );
200 ImplFallback( TWAIN_EVENT_QUIT );
202 return( nRet == TWRC_SUCCESS || nRet == TWRC_CANCEL );
205 // -----------------------------------------------------------------------------
207 BOOL ImpTwain::InitXfer()
209 BOOL bRet = FALSE;
211 if( !!aBitmap )
212 aBitmap = Bitmap();
214 ImplOpenSourceManager();
216 if( 3 == nCurState )
218 ImplOpenSource();
220 if( 4 == nCurState )
221 bRet = ImplEnableSource();
224 if( !bRet )
225 ImplFallback( TWAIN_EVENT_QUIT );
227 return bRet;
230 // -----------------------------------------------------------------------------
232 Bitmap ImpTwain::GetXferBitmap()
234 Bitmap aRet( aBitmap );
235 aBitmap = Bitmap();
236 return aRet;
239 // -----------------------------------------------------------------------------
241 void ImpTwain::ImplOpenSourceManager()
243 if( 1 == nCurState )
245 pMod = new NAMESPACE_VOS( OModule )();
247 if( pMod->load( TWAIN_LIBNAME ) )
249 nCurState = 2;
251 if( ( ( pDSM = (DSMENTRYPROC) pMod->getSymbol( TWAIN_FUNCNAME ) ) != NULL ) &&
252 ( PFUNC( &aAppIdent, NULL, DG_CONTROL, DAT_PARENT, MSG_OPENDSM, &hTwainWnd ) == TWRC_SUCCESS ) )
254 nCurState = 3;
257 else
259 delete pMod;
260 pMod = NULL;
265 // -----------------------------------------------------------------------------
267 void ImpTwain::ImplOpenSource()
269 if( 3 == nCurState )
271 if( ( PFUNC( &aAppIdent, NULL, DG_CONTROL, DAT_IDENTITY, MSG_GETDEFAULT, &aSrcIdent ) == TWRC_SUCCESS ) &&
272 ( PFUNC( &aAppIdent, NULL, DG_CONTROL, DAT_IDENTITY, MSG_OPENDS, &aSrcIdent ) == TWRC_SUCCESS ) )
274 #ifdef OS2
276 // negotiate capabilities
278 #else
280 TW_CAPABILITY aCap = { CAP_XFERCOUNT, TWON_ONEVALUE, GlobalAlloc( GHND, sizeof( TW_ONEVALUE ) ) };
281 TW_ONEVALUE* pVal = (TW_ONEVALUE*) GlobalLock( aCap.hContainer );
283 pVal->ItemType = TWTY_INT16, pVal->Item = 1;
284 GlobalUnlock( aCap.hContainer );
285 PFUNC( &aAppIdent, &aSrcIdent, DG_CONTROL, DAT_CAPABILITY, MSG_SET, &aCap );
286 GlobalFree( aCap.hContainer );
287 #endif
289 nCurState = 4;
294 // -----------------------------------------------------------------------------
296 BOOL ImpTwain::ImplEnableSource()
298 BOOL bRet = FALSE;
300 if( 4 == nCurState )
302 TW_USERINTERFACE aUI = { TRUE, TRUE, hTwainWnd };
304 aNotifyLink.Call( (void*) TWAIN_EVENT_SCANNING );
305 nCurState = 5;
307 if( PFUNC( &aAppIdent, &aSrcIdent, DG_CONTROL, DAT_USERINTERFACE, MSG_ENABLEDS, &aUI ) == TWRC_SUCCESS )
308 bRet = TRUE;
309 else
310 nCurState = 4;
313 return bRet;
316 // -----------------------------------------------------------------------------
318 BOOL ImpTwain::ImplHandleMsg( void* pMsg )
320 TW_UINT16 nRet;
321 PTWAINMSG pMess = (PTWAINMSG) pMsg;
322 TW_EVENT aEvt = { pMess, MSG_NULL };
324 nRet = PFUNC( &aAppIdent, &aSrcIdent, DG_CONTROL, DAT_EVENT, MSG_PROCESSEVENT, &aEvt );
326 if( aEvt.TWMessage != MSG_NULL )
328 switch( aEvt.TWMessage )
330 case MSG_XFERREADY:
332 ULONG nEvent = TWAIN_EVENT_QUIT;
334 if( 5 == nCurState )
336 nCurState = 6;
337 ImplXfer();
339 if( !!aBitmap )
340 nEvent = TWAIN_EVENT_XFER;
343 ImplFallback( nEvent );
345 break;
347 case MSG_CLOSEDSREQ:
348 ImplFallback( TWAIN_EVENT_QUIT );
349 break;
351 default:
352 break;
355 else
356 nRet = TWRC_NOTDSEVENT;
358 return( TWRC_DSEVENT == nRet );
361 // -----------------------------------------------------------------------------
363 void ImpTwain::ImplXfer()
365 if( nCurState == 6 )
367 TW_IMAGEINFO aInfo;
368 TW_UINT32 hDIB = 0;
369 long nWidth = aInfo.ImageWidth;
370 long nHeight = aInfo.ImageLength;
371 long nXRes = FIXTOLONG( aInfo.XResolution );
372 long nYRes = FIXTOLONG( aInfo.YResolution );
374 if( PFUNC( &aAppIdent, &aSrcIdent, DG_IMAGE, DAT_IMAGEINFO, MSG_GET, &aInfo ) == TWRC_SUCCESS )
376 nWidth = aInfo.ImageWidth;
377 nHeight = aInfo.ImageLength;
378 nXRes = FIXTOLONG( aInfo.XResolution );
379 nYRes = FIXTOLONG( aInfo.YResolution );
381 else
382 nWidth = nHeight = nXRes = nYRes = -1L;
384 switch( PFUNC( &aAppIdent, &aSrcIdent, DG_IMAGE, DAT_IMAGENATIVEXFER, MSG_GET, &hDIB ) )
386 case( TWRC_CANCEL ):
387 nCurState = 7;
388 break;
390 case( TWRC_XFERDONE ):
392 #ifdef OS2
394 // get OS/2-Bitmap
396 #else // OS2
397 const ULONG nSize = GlobalSize( (HGLOBAL) hDIB );
398 char* pBuf = (char*) GlobalLock( (HGLOBAL) hDIB );
400 if( pBuf )
402 SvMemoryStream aMemStm;
403 aMemStm.SetBuffer( pBuf, nSize, FALSE, nSize );
404 aBitmap.Read( aMemStm, FALSE );
405 GlobalUnlock( (HGLOBAL) hDIB );
408 GlobalFree( (HGLOBAL) hDIB );
409 #endif // OS2
411 // set resolution of bitmap if neccessary
412 if ( ( nXRes != -1 ) && ( nYRes != - 1 ) && ( nWidth != - 1 ) && ( nHeight != - 1 ) )
414 const MapMode aMapMode( MAP_100TH_INCH, Point(), Fraction( 100, nXRes ), Fraction( 100, nYRes ) );
415 aBitmap.SetPrefMapMode( aMapMode );
416 aBitmap.SetPrefSize( Size( nWidth, nHeight ) );
419 nCurState = 7;
421 break;
423 default:
424 break;
429 // -----------------------------------------------------------------------------
431 void ImpTwain::ImplFallback( ULONG nEvent )
433 Application::PostUserEvent( LINK( this, ImpTwain, ImplFallbackHdl ), (void*) nEvent );
436 // -----------------------------------------------------------------------------
438 IMPL_LINK( ImpTwain, ImplFallbackHdl, void*, pData )
440 const ULONG nEvent = (ULONG) pData;
441 BOOL bFallback = TRUE;
443 switch( nCurState )
445 case( 7 ):
446 case( 6 ):
448 TW_PENDINGXFERS aXfers;
450 if( PFUNC( &aAppIdent, &aSrcIdent, DG_CONTROL, DAT_PENDINGXFERS, MSG_ENDXFER, &aXfers ) == TWRC_SUCCESS )
452 if( aXfers.Count != 0 )
453 PFUNC( &aAppIdent, &aSrcIdent, DG_CONTROL, DAT_PENDINGXFERS, MSG_RESET, &aXfers );
456 nCurState = 5;
458 break;
460 case( 5 ):
462 TW_USERINTERFACE aUI = { TRUE, TRUE, hTwainWnd };
464 PFUNC( &aAppIdent, &aSrcIdent, DG_CONTROL, DAT_USERINTERFACE, MSG_DISABLEDS, &aUI );
465 nCurState = 4;
467 break;
469 case( 4 ):
471 PFUNC( &aAppIdent, NULL, DG_CONTROL, DAT_IDENTITY, MSG_CLOSEDS, &aSrcIdent );
472 nCurState = 3;
474 break;
476 case( 3 ):
478 PFUNC( &aAppIdent, NULL, DG_CONTROL, DAT_PARENT, MSG_CLOSEDSM, &hTwainWnd );
479 nCurState = 2;
481 break;
483 case( 2 ):
485 delete pMod;
486 pMod = NULL;
487 nCurState = 1;
489 break;
491 default:
493 if( nEvent != TWAIN_EVENT_NONE )
494 aNotifyLink.Call( (void*) nEvent );
496 bFallback = FALSE;
498 break;
501 if( bFallback )
502 ImplFallback( nEvent );
504 return 0L;
507 // -----------------------------------------------------------------------------
509 IMPL_LINK( ImpTwain, ImplDestroyHdl, void*, p )
511 #ifdef OS2
513 if( hWndTwain )
514 WinDestroyWindow( hWndTwain );
516 // unset hook
518 #else
520 if( hTwainWnd )
521 DestroyWindow( hTwainWnd );
523 if( hTwainHook )
524 UnhookWindowsHookEx( hTwainHook );
526 #endif
528 delete this;
529 pImpTwainInstance = NULL;
531 return 0L;