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