00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037 #include "precompiled_extensions.hxx"
00038
00039 #include <string.h>
00040 #include <math.h>
00041
00042 #if defined( WNT ) || defined (WIN)
00043 #include <tools/svwin.h>
00044 #endif
00045 #ifdef OS2
00046 #include <svpm.h>
00047 #endif // OS2
00048 #include <vos/module.hxx>
00049 #include <tools/stream.hxx>
00050 #include <vcl/svapp.hxx>
00051 #include <vcl/wrkwin.hxx>
00052 #include <vcl/sysdata.hxx>
00053 #include "twain.hxx"
00054
00055
00056
00057
00058
00059 #define PFUNC (*pDSM)
00060 #define FIXTODOUBLE( nFix ) ((double)nFix.Whole+(double)nFix.Frac/65536.)
00061 #define FIXTOLONG( nFix ) ((long)floor(FIXTODOUBLE(nFix)+0.5))
00062
00063 #if defined WIN
00064 #define TWAIN_LIBNAME "TWAIN.DLL"
00065 #define TWAIN_FUNCNAME "DSM_Entry"
00066 #elif defined WNT
00067 #define TWAIN_LIBNAME "TWAIN_32.DLL"
00068 #define TWAIN_FUNCNAME "DSM_Entry"
00069 #elif defined OS2
00070 #define TWAIN_LIBNAME "twain"
00071 #define TWAIN_FUNCNAME "DSM_ENTRY"
00072 #endif
00073
00074
00075
00076
00077
00078 static ImpTwain* pImpTwainInstance = NULL;
00079
00080
00081
00082
00083
00084 #ifdef OS2
00085
00086 #define PTWAINMSG QMSG*
00087
00088 MRESULT EXPENTRY TwainWndProc( HWND hWnd, ULONG nMsg, MPARAM nParam1, MPARAM nParam2 )
00089 {
00090 return (MRESULT) TRUE;
00091 }
00092
00093
00094 #else // OS2
00095
00096 #define PTWAINMSG MSG*
00097
00098
00099
00100 LRESULT CALLBACK TwainWndProc( HWND hWnd,UINT nMsg, WPARAM nPar1, LPARAM nPar2 )
00101 {
00102 return DefWindowProc( hWnd, nMsg, nPar1, nPar2 );
00103 }
00104
00105
00106
00107 LRESULT CALLBACK TwainMsgProc( int nCode, WPARAM wParam, LPARAM lParam )
00108 {
00109 MSG* pMsg = (MSG*) lParam;
00110
00111 if( ( nCode < 0 ) ||
00112 ( pImpTwainInstance->hTwainWnd != pMsg->hwnd ) ||
00113 !pImpTwainInstance->ImplHandleMsg( (void*) lParam ) )
00114 {
00115 return CallNextHookEx( pImpTwainInstance->hTwainHook, nCode, wParam, lParam );
00116 }
00117 else
00118 {
00119 pMsg->message = WM_USER;
00120 pMsg->lParam = 0;
00121
00122 return 0;
00123 }
00124 }
00125
00126 #endif // OS2
00127
00128
00129
00130
00131
00132 ImpTwain::ImpTwain( const Link& rNotifyLink ) :
00133 aNotifyLink ( rNotifyLink ),
00134 pDSM ( NULL ),
00135 pMod ( NULL ),
00136 hTwainWnd ( 0 ),
00137 hTwainHook ( 0 ),
00138 nCurState ( 1 )
00139 {
00140 pImpTwainInstance = this;
00141
00142 aAppIdent.Id = 0;
00143 aAppIdent.Version.MajorNum = 1;
00144 aAppIdent.Version.MinorNum = 0;
00145 aAppIdent.Version.Language = TWLG_USA;
00146 aAppIdent.Version.Country = TWCY_USA;
00147 aAppIdent.ProtocolMajor = TWON_PROTOCOLMAJOR;
00148 aAppIdent.ProtocolMinor = TWON_PROTOCOLMINOR;
00149 aAppIdent.SupportedGroups = DG_IMAGE | DG_CONTROL;
00150 strcpy( aAppIdent.Version.Info, "6.0" );
00151 strcpy( aAppIdent.Manufacturer, "Sun Microsystems");
00152 strcpy( aAppIdent.ProductFamily,"Office");
00153 strcpy( aAppIdent.ProductName, "Office");
00154
00155 #ifdef OS2
00156
00157 hAB = Sysdepen::GethAB();
00158 ImplFallback( TWAIN_EVENT_QUIT );
00159
00160
00161 #else
00162
00163 HWND hParentWnd = HWND_DESKTOP;
00164 WNDCLASS aWc = { 0, &TwainWndProc, 0, sizeof( WNDCLASS ), GetModuleHandle( NULL ),
00165 NULL, NULL, NULL, NULL, "TwainClass" };
00166
00167 RegisterClass( &aWc );
00168 hTwainWnd = CreateWindowEx( WS_EX_TOPMOST, aWc.lpszClassName, "TWAIN", 0, 0, 0, 0, 0, hParentWnd, NULL, aWc.hInstance, 0 );
00169 hTwainHook = SetWindowsHookEx( WH_GETMESSAGE, &TwainMsgProc, NULL, GetCurrentThreadId() );
00170
00171 #endif
00172 }
00173
00174
00175
00176 ImpTwain::~ImpTwain()
00177 {
00178 }
00179
00180
00181
00182 void ImpTwain::Destroy()
00183 {
00184 ImplFallback( TWAIN_EVENT_NONE );
00185 Application::PostUserEvent( LINK( this, ImpTwain, ImplDestroyHdl ), NULL );
00186 }
00187
00188
00189
00190 BOOL ImpTwain::SelectSource()
00191 {
00192 TW_UINT16 nRet = TWRC_FAILURE;
00193
00194 if( !!aBitmap )
00195 aBitmap = Bitmap();
00196
00197 ImplOpenSourceManager();
00198
00199 if( 3 == nCurState )
00200 {
00201 TW_IDENTITY aIdent;
00202
00203 aIdent.Id = 0, aIdent.ProductName[ 0 ] = '\0';
00204 aNotifyLink.Call( (void*) TWAIN_EVENT_SCANNING );
00205 nRet = PFUNC( &aAppIdent, NULL, DG_CONTROL, DAT_IDENTITY, MSG_USERSELECT, &aIdent );
00206 }
00207
00208 ImplFallback( TWAIN_EVENT_QUIT );
00209
00210 return( nRet == TWRC_SUCCESS || nRet == TWRC_CANCEL );
00211 }
00212
00213
00214
00215 BOOL ImpTwain::InitXfer()
00216 {
00217 BOOL bRet = FALSE;
00218
00219 if( !!aBitmap )
00220 aBitmap = Bitmap();
00221
00222 ImplOpenSourceManager();
00223
00224 if( 3 == nCurState )
00225 {
00226 ImplOpenSource();
00227
00228 if( 4 == nCurState )
00229 bRet = ImplEnableSource();
00230 }
00231
00232 if( !bRet )
00233 ImplFallback( TWAIN_EVENT_QUIT );
00234
00235 return bRet;
00236 }
00237
00238
00239
00240 Bitmap ImpTwain::GetXferBitmap()
00241 {
00242 Bitmap aRet( aBitmap );
00243 aBitmap = Bitmap();
00244 return aRet;
00245 }
00246
00247
00248
00249 void ImpTwain::ImplOpenSourceManager()
00250 {
00251 if( 1 == nCurState )
00252 {
00253 pMod = new NAMESPACE_VOS( OModule )();
00254
00255 if( pMod->load( TWAIN_LIBNAME ) )
00256 {
00257 nCurState = 2;
00258
00259 if( ( ( pDSM = (DSMENTRYPROC) pMod->getSymbol( TWAIN_FUNCNAME ) ) != NULL ) &&
00260 ( PFUNC( &aAppIdent, NULL, DG_CONTROL, DAT_PARENT, MSG_OPENDSM, &hTwainWnd ) == TWRC_SUCCESS ) )
00261 {
00262 nCurState = 3;
00263 }
00264 }
00265 else
00266 {
00267 delete pMod;
00268 pMod = NULL;
00269 }
00270 }
00271 }
00272
00273
00274
00275 void ImpTwain::ImplOpenSource()
00276 {
00277 if( 3 == nCurState )
00278 {
00279 if( ( PFUNC( &aAppIdent, NULL, DG_CONTROL, DAT_IDENTITY, MSG_GETDEFAULT, &aSrcIdent ) == TWRC_SUCCESS ) &&
00280 ( PFUNC( &aAppIdent, NULL, DG_CONTROL, DAT_IDENTITY, MSG_OPENDS, &aSrcIdent ) == TWRC_SUCCESS ) )
00281 {
00282 #ifdef OS2
00283
00284
00285
00286 #else
00287
00288 TW_CAPABILITY aCap = { CAP_XFERCOUNT, TWON_ONEVALUE, GlobalAlloc( GHND, sizeof( TW_ONEVALUE ) ) };
00289 TW_ONEVALUE* pVal = (TW_ONEVALUE*) GlobalLock( aCap.hContainer );
00290
00291 pVal->ItemType = TWTY_INT16, pVal->Item = 1;
00292 GlobalUnlock( aCap.hContainer );
00293 PFUNC( &aAppIdent, &aSrcIdent, DG_CONTROL, DAT_CAPABILITY, MSG_SET, &aCap );
00294 GlobalFree( aCap.hContainer );
00295 #endif
00296
00297 nCurState = 4;
00298 }
00299 }
00300 }
00301
00302
00303
00304 BOOL ImpTwain::ImplEnableSource()
00305 {
00306 BOOL bRet = FALSE;
00307
00308 if( 4 == nCurState )
00309 {
00310 TW_USERINTERFACE aUI = { TRUE, TRUE, hTwainWnd };
00311
00312 aNotifyLink.Call( (void*) TWAIN_EVENT_SCANNING );
00313 nCurState = 5;
00314
00315 if( PFUNC( &aAppIdent, &aSrcIdent, DG_CONTROL, DAT_USERINTERFACE, MSG_ENABLEDS, &aUI ) == TWRC_SUCCESS )
00316 bRet = TRUE;
00317 else
00318 nCurState = 4;
00319 }
00320
00321 return bRet;
00322 }
00323
00324
00325
00326 BOOL ImpTwain::ImplHandleMsg( void* pMsg )
00327 {
00328 TW_UINT16 nRet;
00329 PTWAINMSG pMess = (PTWAINMSG) pMsg;
00330 TW_EVENT aEvt = { pMess, MSG_NULL };
00331
00332 nRet = PFUNC( &aAppIdent, &aSrcIdent, DG_CONTROL, DAT_EVENT, MSG_PROCESSEVENT, &aEvt );
00333
00334 if( aEvt.TWMessage != MSG_NULL )
00335 {
00336 switch( aEvt.TWMessage )
00337 {
00338 case MSG_XFERREADY:
00339 {
00340 ULONG nEvent = TWAIN_EVENT_QUIT;
00341
00342 if( 5 == nCurState )
00343 {
00344 nCurState = 6;
00345 ImplXfer();
00346
00347 if( !!aBitmap )
00348 nEvent = TWAIN_EVENT_XFER;
00349 }
00350
00351 ImplFallback( nEvent );
00352 }
00353 break;
00354
00355 case MSG_CLOSEDSREQ:
00356 ImplFallback( TWAIN_EVENT_QUIT );
00357 break;
00358
00359 default:
00360 break;
00361 }
00362 }
00363 else
00364 nRet = TWRC_NOTDSEVENT;
00365
00366 return( TWRC_DSEVENT == nRet );
00367 }
00368
00369
00370
00371 void ImpTwain::ImplXfer()
00372 {
00373 if( nCurState == 6 )
00374 {
00375 TW_IMAGEINFO aInfo;
00376 TW_UINT32 hDIB = 0;
00377 long nWidth = aInfo.ImageWidth;
00378 long nHeight = aInfo.ImageLength;
00379 long nXRes = FIXTOLONG( aInfo.XResolution );
00380 long nYRes = FIXTOLONG( aInfo.YResolution );
00381
00382 if( PFUNC( &aAppIdent, &aSrcIdent, DG_IMAGE, DAT_IMAGEINFO, MSG_GET, &aInfo ) == TWRC_SUCCESS )
00383 {
00384 nWidth = aInfo.ImageWidth;
00385 nHeight = aInfo.ImageLength;
00386 nXRes = FIXTOLONG( aInfo.XResolution );
00387 nYRes = FIXTOLONG( aInfo.YResolution );
00388 }
00389 else
00390 nWidth = nHeight = nXRes = nYRes = -1L;
00391
00392 switch( PFUNC( &aAppIdent, &aSrcIdent, DG_IMAGE, DAT_IMAGENATIVEXFER, MSG_GET, &hDIB ) )
00393 {
00394 case( TWRC_CANCEL ):
00395 nCurState = 7;
00396 break;
00397
00398 case( TWRC_XFERDONE ):
00399 {
00400 #ifdef OS2
00401
00402
00403
00404 #else // OS2
00405 const ULONG nSize = GlobalSize( (HGLOBAL) hDIB );
00406 char* pBuf = (char*) GlobalLock( (HGLOBAL) hDIB );
00407
00408 if( pBuf )
00409 {
00410 SvMemoryStream aMemStm;
00411 aMemStm.SetBuffer( pBuf, nSize, FALSE, nSize );
00412 aBitmap.Read( aMemStm, FALSE );
00413 GlobalUnlock( (HGLOBAL) hDIB );
00414 }
00415
00416 GlobalFree( (HGLOBAL) hDIB );
00417 #endif // OS2
00418
00419
00420 if ( ( nXRes != -1 ) && ( nYRes != - 1 ) && ( nWidth != - 1 ) && ( nHeight != - 1 ) )
00421 {
00422 const MapMode aMapMode( MAP_100TH_INCH, Point(), Fraction( 100, nXRes ), Fraction( 100, nYRes ) );
00423 aBitmap.SetPrefMapMode( aMapMode );
00424 aBitmap.SetPrefSize( Size( nWidth, nHeight ) );
00425 }
00426
00427 nCurState = 7;
00428 }
00429 break;
00430
00431 default:
00432 break;
00433 }
00434 }
00435 }
00436
00437
00438
00439 void ImpTwain::ImplFallback( ULONG nEvent )
00440 {
00441 Application::PostUserEvent( LINK( this, ImpTwain, ImplFallbackHdl ), (void*) nEvent );
00442 }
00443
00444
00445
00446 IMPL_LINK( ImpTwain, ImplFallbackHdl, void*, pData )
00447 {
00448 const ULONG nEvent = (ULONG) pData;
00449 BOOL bFallback = TRUE;
00450
00451 switch( nCurState )
00452 {
00453 case( 7 ):
00454 case( 6 ):
00455 {
00456 TW_PENDINGXFERS aXfers;
00457
00458 if( PFUNC( &aAppIdent, &aSrcIdent, DG_CONTROL, DAT_PENDINGXFERS, MSG_ENDXFER, &aXfers ) == TWRC_SUCCESS )
00459 {
00460 if( aXfers.Count != 0 )
00461 PFUNC( &aAppIdent, &aSrcIdent, DG_CONTROL, DAT_PENDINGXFERS, MSG_RESET, &aXfers );
00462 }
00463
00464 nCurState = 5;
00465 }
00466 break;
00467
00468 case( 5 ):
00469 {
00470 TW_USERINTERFACE aUI = { TRUE, TRUE, hTwainWnd };
00471
00472 PFUNC( &aAppIdent, &aSrcIdent, DG_CONTROL, DAT_USERINTERFACE, MSG_DISABLEDS, &aUI );
00473 nCurState = 4;
00474 }
00475 break;
00476
00477 case( 4 ):
00478 {
00479 PFUNC( &aAppIdent, NULL, DG_CONTROL, DAT_IDENTITY, MSG_CLOSEDS, &aSrcIdent );
00480 nCurState = 3;
00481 }
00482 break;
00483
00484 case( 3 ):
00485 {
00486 PFUNC( &aAppIdent, NULL, DG_CONTROL, DAT_PARENT, MSG_CLOSEDSM, &hTwainWnd );
00487 nCurState = 2;
00488 }
00489 break;
00490
00491 case( 2 ):
00492 {
00493 delete pMod;
00494 pMod = NULL;
00495 nCurState = 1;
00496 }
00497 break;
00498
00499 default:
00500 {
00501 if( nEvent != TWAIN_EVENT_NONE )
00502 aNotifyLink.Call( (void*) nEvent );
00503
00504 bFallback = FALSE;
00505 }
00506 break;
00507 }
00508
00509 if( bFallback )
00510 ImplFallback( nEvent );
00511
00512 return 0L;
00513 }
00514
00515
00516
00517 IMPL_LINK( ImpTwain, ImplDestroyHdl, void*, p )
00518 {
00519 #ifdef OS2
00520
00521 if( hWndTwain )
00522 WinDestroyWindow( hWndTwain );
00523
00524
00525
00526 #else
00527
00528 if( hTwainWnd )
00529 DestroyWindow( hTwainWnd );
00530
00531 if( hTwainHook )
00532 UnhookWindowsHookEx( hTwainHook );
00533
00534 #endif
00535
00536 delete this;
00537 pImpTwainInstance = NULL;
00538
00539 return 0L;
00540 }