xref: /AOO41X/main/extensions/source/scanner/twain.cxx (revision 2a97ec55f1442d65917e8c8b82a55ab76c9ff676)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_extensions.hxx"
26 
27 #include <string.h>
28 #include <math.h>
29 
30 #if defined( WNT )
31 #include <tools/svwin.h>
32 #endif
33 #ifdef OS2
34 #include <svpm.h>
35 #endif // OS2
36 #include <vos/module.hxx>
37 #include <tools/stream.hxx>
38 #include <vcl/svapp.hxx>
39 #include <vcl/wrkwin.hxx>
40 #include <vcl/sysdata.hxx>
41 #include "twain.hxx"
42 
43 // -----------
44 // - Defines -
45 // -----------
46 
47 #define PFUNC                       (*pDSM)
48 #define FIXTODOUBLE( nFix )         ((double)nFix.Whole+(double)nFix.Frac/65536.)
49 #define FIXTOLONG( nFix )           ((long)floor(FIXTODOUBLE(nFix)+0.5))
50 
51 #if defined WNT
52 #define TWAIN_LIBNAME               "TWAIN_32.DLL"
53 #define TWAIN_FUNCNAME              "DSM_Entry"
54 #elif defined OS2
55 #define TWAIN_LIBNAME               "twain"
56 #define TWAIN_FUNCNAME              "DSM_ENTRY"
57 #endif
58 
59 // -----------
60 // - Statics -
61 // -----------
62 
63 static ImpTwain* pImpTwainInstance = NULL;
64 
65 // ---------
66 // - Procs -
67 // ---------
68 
69 #ifdef OS2
70 
71     #define PTWAINMSG QMSG*
72 
TwainWndProc(HWND hWnd,ULONG nMsg,MPARAM nParam1,MPARAM nParam2)73     MRESULT EXPENTRY TwainWndProc( HWND hWnd, ULONG nMsg, MPARAM nParam1, MPARAM nParam2 )
74     {
75         return (MRESULT) TRUE;
76     }
77 
78 
79 #else // OS2
80 
81     #define PTWAINMSG MSG*
82 
83     // -------------------------------------------------------------------------
84 
TwainWndProc(HWND hWnd,UINT nMsg,WPARAM nPar1,LPARAM nPar2)85     LRESULT CALLBACK TwainWndProc( HWND hWnd,UINT nMsg, WPARAM nPar1, LPARAM nPar2 )
86     {
87         return DefWindowProc( hWnd, nMsg, nPar1, nPar2 );
88     }
89 
90     // -------------------------------------------------------------------------
91 
TwainMsgProc(int nCode,WPARAM wParam,LPARAM lParam)92     LRESULT CALLBACK TwainMsgProc( int nCode, WPARAM wParam, LPARAM lParam )
93     {
94         MSG* pMsg = (MSG*) lParam;
95 
96         if( ( nCode < 0 ) ||
97             ( pImpTwainInstance->hTwainWnd != pMsg->hwnd ) ||
98             !pImpTwainInstance->ImplHandleMsg( (void*) lParam ) )
99         {
100             return CallNextHookEx( pImpTwainInstance->hTwainHook, nCode, wParam, lParam );
101         }
102         else
103         {
104             pMsg->message = WM_USER;
105             pMsg->lParam = 0;
106 
107             return 0;
108         }
109     }
110 
111 #endif // OS2
112 
113 // ------------
114 // - ImpTwain -
115 // ------------
116 
ImpTwain(const Link & rNotifyLink)117 ImpTwain::ImpTwain( const Link& rNotifyLink ) :
118             aNotifyLink ( rNotifyLink ),
119             pDSM        ( NULL ),
120             pMod        ( NULL ),
121             hTwainWnd   ( 0 ),
122             hTwainHook  ( 0 ),
123             nCurState   ( 1 )
124 {
125     pImpTwainInstance = this;
126 
127     aAppIdent.Id = 0;
128     aAppIdent.Version.MajorNum = 1;
129     aAppIdent.Version.MinorNum = 0;
130     aAppIdent.Version.Language = TWLG_USA;
131     aAppIdent.Version.Country = TWCY_USA;
132     aAppIdent.ProtocolMajor = TWON_PROTOCOLMAJOR;
133     aAppIdent.ProtocolMinor = TWON_PROTOCOLMINOR;
134     aAppIdent.SupportedGroups = DG_IMAGE | DG_CONTROL;
135     strcpy( aAppIdent.Version.Info, "6.0" );
136     strcpy( aAppIdent.Manufacturer, "Sun Microsystems");
137     strcpy( aAppIdent.ProductFamily,"Office");
138     strcpy( aAppIdent.ProductName, "Office");
139 
140 #ifdef OS2
141 
142     hAB = Sysdepen::GethAB();
143     ImplFallback( TWAIN_EVENT_QUIT );
144     // hTwainWnd = WinCreateWindow( HWND_DESKTOP, WC_FRAME, "dummy", 0, 0, 0, 0, 0, HWND_DESKTOP, HWND_BOTTOM, 0, 0, 0 );
145 
146 #else
147 
148     HWND        hParentWnd = HWND_DESKTOP;
149     WNDCLASS    aWc = { 0, &TwainWndProc, 0, sizeof( WNDCLASS ), GetModuleHandle( NULL ),
150                         NULL, NULL, NULL, NULL, "TwainClass" };
151 
152     RegisterClass( &aWc );
153     hTwainWnd = CreateWindowEx( WS_EX_TOPMOST, aWc.lpszClassName, "TWAIN", 0, 0, 0, 0, 0, hParentWnd, NULL, aWc.hInstance, 0 );
154     hTwainHook = SetWindowsHookEx( WH_GETMESSAGE, &TwainMsgProc, NULL, GetCurrentThreadId() );
155 
156 #endif
157 }
158 
159 // -----------------------------------------------------------------------------
160 
~ImpTwain()161 ImpTwain::~ImpTwain()
162 {
163 }
164 
165 // -----------------------------------------------------------------------------
166 
Destroy()167 void ImpTwain::Destroy()
168 {
169     ImplFallback( TWAIN_EVENT_NONE );
170     Application::PostUserEvent( LINK( this, ImpTwain, ImplDestroyHdl ), NULL );
171 }
172 
173 // -----------------------------------------------------------------------------
174 
SelectSource()175 sal_Bool ImpTwain::SelectSource()
176 {
177     TW_UINT16 nRet = TWRC_FAILURE;
178 
179     if( !!aBitmap )
180         aBitmap = Bitmap();
181 
182     ImplOpenSourceManager();
183 
184     if( 3 == nCurState )
185     {
186         TW_IDENTITY aIdent;
187 
188         aIdent.Id = 0, aIdent.ProductName[ 0 ] = '\0';
189         aNotifyLink.Call( (void*) TWAIN_EVENT_SCANNING );
190         nRet = PFUNC( &aAppIdent, NULL, DG_CONTROL, DAT_IDENTITY, MSG_USERSELECT, &aIdent );
191     }
192 
193     ImplFallback( TWAIN_EVENT_QUIT );
194 
195     return( nRet == TWRC_SUCCESS || nRet == TWRC_CANCEL );
196 }
197 
198 // -----------------------------------------------------------------------------
199 
InitXfer()200 sal_Bool ImpTwain::InitXfer()
201 {
202     sal_Bool bRet = sal_False;
203 
204     if( !!aBitmap )
205         aBitmap = Bitmap();
206 
207     ImplOpenSourceManager();
208 
209     if( 3 == nCurState )
210     {
211         ImplOpenSource();
212 
213         if( 4 == nCurState )
214             bRet = ImplEnableSource();
215     }
216 
217     if( !bRet )
218         ImplFallback( TWAIN_EVENT_QUIT );
219 
220     return bRet;
221 }
222 
223 // -----------------------------------------------------------------------------
224 
GetXferBitmap()225 Bitmap ImpTwain::GetXferBitmap()
226 {
227     Bitmap aRet( aBitmap );
228     aBitmap = Bitmap();
229     return aRet;
230 }
231 
232 // -----------------------------------------------------------------------------
233 
ImplOpenSourceManager()234 void ImpTwain::ImplOpenSourceManager()
235 {
236     if( 1 == nCurState )
237     {
238         pMod = new vos:: OModule ();
239 
240         if( pMod->load( TWAIN_LIBNAME ) )
241         {
242             nCurState = 2;
243 
244             if( ( ( pDSM = (DSMENTRYPROC) pMod->getSymbol( TWAIN_FUNCNAME ) ) != NULL ) &&
245                 ( PFUNC( &aAppIdent, NULL, DG_CONTROL, DAT_PARENT, MSG_OPENDSM, &hTwainWnd ) == TWRC_SUCCESS ) )
246             {
247                 nCurState = 3;
248             }
249         }
250         else
251         {
252             delete pMod;
253             pMod = NULL;
254         }
255     }
256 }
257 
258 // -----------------------------------------------------------------------------
259 
ImplOpenSource()260 void ImpTwain::ImplOpenSource()
261 {
262     if( 3 == nCurState )
263     {
264         if( ( PFUNC( &aAppIdent, NULL, DG_CONTROL, DAT_IDENTITY, MSG_GETDEFAULT, &aSrcIdent ) == TWRC_SUCCESS ) &&
265             ( PFUNC( &aAppIdent, NULL, DG_CONTROL, DAT_IDENTITY, MSG_OPENDS, &aSrcIdent ) == TWRC_SUCCESS ) )
266         {
267 #ifdef OS2
268 
269             // negotiate capabilities
270 
271 #else
272 
273             TW_CAPABILITY   aCap = { CAP_XFERCOUNT, TWON_ONEVALUE, GlobalAlloc( GHND, sizeof( TW_ONEVALUE ) ) };
274             TW_ONEVALUE*    pVal = (TW_ONEVALUE*) GlobalLock( aCap.hContainer );
275 
276             pVal->ItemType = TWTY_INT16, pVal->Item = 1;
277             GlobalUnlock( aCap.hContainer );
278             PFUNC( &aAppIdent, &aSrcIdent, DG_CONTROL, DAT_CAPABILITY, MSG_SET, &aCap );
279             GlobalFree( aCap.hContainer );
280 #endif
281 
282             nCurState = 4;
283         }
284     }
285 }
286 
287 // -----------------------------------------------------------------------------
288 
ImplEnableSource()289 BOOL ImpTwain::ImplEnableSource()
290 {
291     BOOL bRet = FALSE;
292 
293     if( 4 == nCurState )
294     {
295         TW_USERINTERFACE aUI = { TRUE, TRUE, hTwainWnd };
296 
297         aNotifyLink.Call( (void*) TWAIN_EVENT_SCANNING );
298         nCurState = 5;
299 
300         if( PFUNC( &aAppIdent, &aSrcIdent, DG_CONTROL, DAT_USERINTERFACE, MSG_ENABLEDS, &aUI ) == TWRC_SUCCESS )
301             bRet = TRUE;
302         else
303             nCurState = 4;
304     }
305 
306     return bRet;
307 }
308 
309 // -----------------------------------------------------------------------------
310 
ImplHandleMsg(void * pMsg)311 BOOL ImpTwain::ImplHandleMsg( void* pMsg )
312 {
313     TW_UINT16   nRet;
314     PTWAINMSG   pMess = (PTWAINMSG) pMsg;
315     TW_EVENT    aEvt = { pMess, MSG_NULL };
316 
317     nRet = PFUNC( &aAppIdent, &aSrcIdent, DG_CONTROL, DAT_EVENT, MSG_PROCESSEVENT, &aEvt );
318 
319     if( aEvt.TWMessage != MSG_NULL )
320     {
321         switch( aEvt.TWMessage )
322         {
323             case MSG_XFERREADY:
324             {
325                 ULONG nEvent = TWAIN_EVENT_QUIT;
326 
327                 if( 5 == nCurState )
328                 {
329                     nCurState = 6;
330                     ImplXfer();
331 
332                     if( !!aBitmap )
333                         nEvent = TWAIN_EVENT_XFER;
334                 }
335 
336                 ImplFallback( nEvent );
337             }
338             break;
339 
340             case MSG_CLOSEDSREQ:
341                 ImplFallback( TWAIN_EVENT_QUIT );
342             break;
343 
344             default:
345             break;
346         }
347     }
348     else
349         nRet = TWRC_NOTDSEVENT;
350 
351     return( TWRC_DSEVENT == nRet );
352 }
353 
354 // -----------------------------------------------------------------------------
355 
ImplXfer()356 void ImpTwain::ImplXfer()
357 {
358     if( nCurState == 6 )
359     {
360         TW_IMAGEINFO    aInfo;
361         TW_UINT32       hDIB = 0;
362         long            nWidth = aInfo.ImageWidth;
363         long            nHeight = aInfo.ImageLength;
364         long            nXRes = FIXTOLONG( aInfo.XResolution );
365         long            nYRes = FIXTOLONG( aInfo.YResolution );
366 
367         if( PFUNC( &aAppIdent, &aSrcIdent, DG_IMAGE, DAT_IMAGEINFO, MSG_GET, &aInfo ) == TWRC_SUCCESS )
368         {
369             nWidth = aInfo.ImageWidth;
370             nHeight = aInfo.ImageLength;
371             nXRes = FIXTOLONG( aInfo.XResolution );
372             nYRes = FIXTOLONG( aInfo.YResolution );
373         }
374         else
375             nWidth = nHeight = nXRes = nYRes = -1L;
376 
377         switch( PFUNC( &aAppIdent, &aSrcIdent, DG_IMAGE, DAT_IMAGENATIVEXFER, MSG_GET, &hDIB ) )
378         {
379             case( TWRC_CANCEL ):
380                 nCurState = 7;
381             break;
382 
383             case( TWRC_XFERDONE ):
384             {
385 #ifdef OS2
386 
387                 // get OS/2-Bitmap
388 
389 #else // OS2
390                 const ULONG nSize = GlobalSize( (HGLOBAL) hDIB );
391                 char*       pBuf = (char*) GlobalLock( (HGLOBAL) hDIB );
392 
393                 if( pBuf )
394                 {
395                     SvMemoryStream aMemStm;
396                     aMemStm.SetBuffer( pBuf, nSize, FALSE, nSize );
397                     aBitmap.Read( aMemStm, FALSE );
398                     GlobalUnlock( (HGLOBAL) hDIB );
399                 }
400 
401                 GlobalFree( (HGLOBAL) hDIB );
402 #endif // OS2
403 
404                 // set resolution of bitmap if neccessary
405                 if ( ( nXRes != -1 ) && ( nYRes != - 1 ) && ( nWidth != - 1 ) && ( nHeight != - 1 ) )
406                 {
407                     const MapMode aMapMode( MAP_100TH_INCH, Point(), Fraction( 100, nXRes ), Fraction( 100, nYRes ) );
408                     aBitmap.SetPrefMapMode( aMapMode );
409                     aBitmap.SetPrefSize( Size( nWidth, nHeight ) );
410                 }
411 
412                 nCurState = 7;
413             }
414             break;
415 
416             default:
417             break;
418         }
419     }
420 }
421 
422 // -----------------------------------------------------------------------------
423 
ImplFallback(ULONG nEvent)424 void ImpTwain::ImplFallback( ULONG nEvent )
425 {
426     Application::PostUserEvent( LINK( this, ImpTwain, ImplFallbackHdl ), (void*) nEvent );
427 }
428 
429 // -----------------------------------------------------------------------------
430 
IMPL_LINK(ImpTwain,ImplFallbackHdl,void *,pData)431 IMPL_LINK( ImpTwain, ImplFallbackHdl, void*, pData )
432 {
433     const ULONG nEvent = (ULONG) pData;
434     sal_Bool        bFallback = sal_True;
435 
436     switch( nCurState )
437     {
438         case( 7 ):
439         case( 6 ):
440         {
441             TW_PENDINGXFERS aXfers;
442 
443             if( PFUNC( &aAppIdent, &aSrcIdent, DG_CONTROL, DAT_PENDINGXFERS, MSG_ENDXFER, &aXfers ) == TWRC_SUCCESS )
444             {
445                 if( aXfers.Count != 0 )
446                     PFUNC( &aAppIdent, &aSrcIdent, DG_CONTROL, DAT_PENDINGXFERS, MSG_RESET, &aXfers );
447             }
448 
449             nCurState = 5;
450         }
451         break;
452 
453         case( 5 ):
454         {
455             TW_USERINTERFACE aUI = { TRUE, TRUE, hTwainWnd };
456 
457             PFUNC( &aAppIdent, &aSrcIdent, DG_CONTROL, DAT_USERINTERFACE, MSG_DISABLEDS, &aUI );
458             nCurState = 4;
459         }
460         break;
461 
462         case( 4 ):
463         {
464             PFUNC( &aAppIdent, NULL, DG_CONTROL, DAT_IDENTITY, MSG_CLOSEDS, &aSrcIdent );
465             nCurState = 3;
466         }
467         break;
468 
469         case( 3 ):
470         {
471             PFUNC( &aAppIdent, NULL, DG_CONTROL, DAT_PARENT, MSG_CLOSEDSM, &hTwainWnd );
472             nCurState = 2;
473         }
474         break;
475 
476         case( 2 ):
477         {
478             delete pMod;
479             pMod = NULL;
480             nCurState = 1;
481         }
482         break;
483 
484         default:
485         {
486             if( nEvent != TWAIN_EVENT_NONE )
487                 aNotifyLink.Call( (void*) nEvent );
488 
489             bFallback = sal_False;
490         }
491         break;
492     }
493 
494     if( bFallback )
495         ImplFallback( nEvent );
496 
497     return 0L;
498 }
499 
500 // -----------------------------------------------------------------------------
501 
IMPL_LINK(ImpTwain,ImplDestroyHdl,void *,p)502 IMPL_LINK( ImpTwain, ImplDestroyHdl, void*, p )
503 {
504 #ifdef OS2
505 
506     if( hWndTwain )
507         WinDestroyWindow( hWndTwain );
508 
509     // unset hook
510 
511 #else
512 
513     if( hTwainWnd )
514         DestroyWindow( hTwainWnd );
515 
516     if( hTwainHook )
517         UnhookWindowsHookEx( hTwainHook );
518 
519 #endif
520 
521     delete this;
522     pImpTwainInstance = NULL;
523 
524     return 0L;
525 }
526